Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. math.round function has a bug?

math.round function has a bug?

Scheduled Pinned Locked Moved Visual Basic
helptutorialquestion
11 Posts 9 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    CICCIOLO69
    wrote on last edited by
    #1

    I'll try to explain : look this example : Module Module1 Sub Main() Dim num AsDouble = 1.25 Console.WriteLine(Math.Round(num, 1, MidpointRounding.AwayFromZero)) num = 1.225 Console.WriteLine(Math.Round(num, 2, MidpointRounding.AwayFromZero)) num = 1.2225 Console.WriteLine(Math.Round(num, 3, MidpointRounding.AwayFromZero)) num = 1.22225 Console.WriteLine(Math.Round(num, 4, MidpointRounding.AwayFromZero)) num = 1.222225 Console.WriteLine(Math.Round(num, 5, MidpointRounding.AwayFromZero)) num = 1.2222225 Console.WriteLine(Math.Round(num, 6, MidpointRounding.AwayFromZero)) EndSub End Module The output of this sample console application is : 1,3 1,23 1,223 1,2223 1,22222 1,222223 Is there something wrong ? In my application I must use five decimal digits and this round method. Regards Andrea

    G C S G T 5 Replies Last reply
    0
    • C CICCIOLO69

      I'll try to explain : look this example : Module Module1 Sub Main() Dim num AsDouble = 1.25 Console.WriteLine(Math.Round(num, 1, MidpointRounding.AwayFromZero)) num = 1.225 Console.WriteLine(Math.Round(num, 2, MidpointRounding.AwayFromZero)) num = 1.2225 Console.WriteLine(Math.Round(num, 3, MidpointRounding.AwayFromZero)) num = 1.22225 Console.WriteLine(Math.Round(num, 4, MidpointRounding.AwayFromZero)) num = 1.222225 Console.WriteLine(Math.Round(num, 5, MidpointRounding.AwayFromZero)) num = 1.2222225 Console.WriteLine(Math.Round(num, 6, MidpointRounding.AwayFromZero)) EndSub End Module The output of this sample console application is : 1,3 1,23 1,223 1,2223 1,22222 1,222223 Is there something wrong ? In my application I must use five decimal digits and this round method. Regards Andrea

      G Offline
      G Offline
      Guffa
      wrote on last edited by
      #2

      No, there isn't anything wrong with the Round method. The problem is your expectations on the double data type. You think that you are putting the exact value 1.222225 in the variable, but that number (as most numbers) can not be exactly represented as a double. What you are actually putting in the variable is something very close to that value, something like 1.22222499999834, which does of course round to 1.22222.

      Despite everything, the person most likely to be fooling you next is yourself.

      S 1 Reply Last reply
      0
      • C CICCIOLO69

        I'll try to explain : look this example : Module Module1 Sub Main() Dim num AsDouble = 1.25 Console.WriteLine(Math.Round(num, 1, MidpointRounding.AwayFromZero)) num = 1.225 Console.WriteLine(Math.Round(num, 2, MidpointRounding.AwayFromZero)) num = 1.2225 Console.WriteLine(Math.Round(num, 3, MidpointRounding.AwayFromZero)) num = 1.22225 Console.WriteLine(Math.Round(num, 4, MidpointRounding.AwayFromZero)) num = 1.222225 Console.WriteLine(Math.Round(num, 5, MidpointRounding.AwayFromZero)) num = 1.2222225 Console.WriteLine(Math.Round(num, 6, MidpointRounding.AwayFromZero)) EndSub End Module The output of this sample console application is : 1,3 1,23 1,223 1,2223 1,22222 1,222223 Is there something wrong ? In my application I must use five decimal digits and this round method. Regards Andrea

        C Offline
        C Offline
        Chinners
        wrote on last edited by
        #3

        You could try using the DECIMAL type instead of DOUBLE. It is much more accurate, however, a bit slower in use. This should get rid of most of these errors as explained by Guffa

        1 Reply Last reply
        0
        • G Guffa

          No, there isn't anything wrong with the Round method. The problem is your expectations on the double data type. You think that you are putting the exact value 1.222225 in the variable, but that number (as most numbers) can not be exactly represented as a double. What you are actually putting in the variable is something very close to that value, something like 1.22222499999834, which does of course round to 1.22222.

          Despite everything, the person most likely to be fooling you next is yourself.

          S Offline
          S Offline
          supercat9
          wrote on last edited by
          #4

          Guffa wrote:

          You think that you are putting the exact value 1.222225 in the variable, but that number (as most numbers) can not be exactly represented as a double. What you are actually putting in the variable is something very close to that value, something like 1.22222499999834, which does of course round to 1.22222.

          Is there any function to increase a double by the smallest possible non-zero amount? I would expect one could do something like:

          Function BumpDouble(ByVal Num As Double) As Double
          Dim Delta, NewVal As Double

          Delta = Num / 36028797018963968 ' (2^55)
          If Delta <> 0 Then
          Do
          NewVal = Num+Delta
          Delta *= 2
          Loop While Num = NewVal
          Else
          ' Need special handling for really really small numbers
          End If
          Return NewVal
          End Function

          But that seems a bit hokey.

          S 1 Reply Last reply
          0
          • C CICCIOLO69

            I'll try to explain : look this example : Module Module1 Sub Main() Dim num AsDouble = 1.25 Console.WriteLine(Math.Round(num, 1, MidpointRounding.AwayFromZero)) num = 1.225 Console.WriteLine(Math.Round(num, 2, MidpointRounding.AwayFromZero)) num = 1.2225 Console.WriteLine(Math.Round(num, 3, MidpointRounding.AwayFromZero)) num = 1.22225 Console.WriteLine(Math.Round(num, 4, MidpointRounding.AwayFromZero)) num = 1.222225 Console.WriteLine(Math.Round(num, 5, MidpointRounding.AwayFromZero)) num = 1.2222225 Console.WriteLine(Math.Round(num, 6, MidpointRounding.AwayFromZero)) EndSub End Module The output of this sample console application is : 1,3 1,23 1,223 1,2223 1,22222 1,222223 Is there something wrong ? In my application I must use five decimal digits and this round method. Regards Andrea

            S Offline
            S Offline
            Steve Mayfield
            wrote on last edited by
            #5

            It looks to me liek the round function is working correctly for example for three decimal places 1.2225 since the last digit is 5 the number is rounded up to 1.223 my understanding of round is that a number is rounded down if the digits past the rounding point is 00 <= digits < 50 and rounded up if the digits past the rounding point is 50 <= digits < 100

            Steve

            G 1 Reply Last reply
            0
            • S Steve Mayfield

              It looks to me liek the round function is working correctly for example for three decimal places 1.2225 since the last digit is 5 the number is rounded up to 1.223 my understanding of round is that a number is rounded down if the digits past the rounding point is 00 <= digits < 50 and rounded up if the digits past the rounding point is 50 <= digits < 100

              Steve

              G Offline
              G Offline
              Guffa
              wrote on last edited by
              #6

              You are missing the point. Notice the value 1,22222 that seems to be rounded differently from the others.

              Despite everything, the person most likely to be fooling you next is yourself.

              K 1 Reply Last reply
              0
              • G Guffa

                You are missing the point. Notice the value 1,22222 that seems to be rounded differently from the others.

                Despite everything, the person most likely to be fooling you next is yourself.

                K Offline
                K Offline
                Kel_
                wrote on last edited by
                #7

                Yeah actually single(float) and double are working the same way, it's not precise, because it's floating-point numbers representation. So it's a lot better and precise to use fixed-point number representation = Decimal in .Net :)


                -- Everything is possible, even the impossible! ^_^

                1 Reply Last reply
                0
                • S supercat9

                  Guffa wrote:

                  You think that you are putting the exact value 1.222225 in the variable, but that number (as most numbers) can not be exactly represented as a double. What you are actually putting in the variable is something very close to that value, something like 1.22222499999834, which does of course round to 1.22222.

                  Is there any function to increase a double by the smallest possible non-zero amount? I would expect one could do something like:

                  Function BumpDouble(ByVal Num As Double) As Double
                  Dim Delta, NewVal As Double

                  Delta = Num / 36028797018963968 ' (2^55)
                  If Delta <> 0 Then
                  Do
                  NewVal = Num+Delta
                  Delta *= 2
                  Loop While Num = NewVal
                  Else
                  ' Need special handling for really really small numbers
                  End If
                  Return NewVal
                  End Function

                  But that seems a bit hokey.

                  S Offline
                  S Offline
                  Stuart Dootson
                  wrote on last edited by
                  #8

                  Rather than try to compute Delta, use Double.Epsilon instead - then you could just do Num + Delta.

                  S 1 Reply Last reply
                  0
                  • C CICCIOLO69

                    I'll try to explain : look this example : Module Module1 Sub Main() Dim num AsDouble = 1.25 Console.WriteLine(Math.Round(num, 1, MidpointRounding.AwayFromZero)) num = 1.225 Console.WriteLine(Math.Round(num, 2, MidpointRounding.AwayFromZero)) num = 1.2225 Console.WriteLine(Math.Round(num, 3, MidpointRounding.AwayFromZero)) num = 1.22225 Console.WriteLine(Math.Round(num, 4, MidpointRounding.AwayFromZero)) num = 1.222225 Console.WriteLine(Math.Round(num, 5, MidpointRounding.AwayFromZero)) num = 1.2222225 Console.WriteLine(Math.Round(num, 6, MidpointRounding.AwayFromZero)) EndSub End Module The output of this sample console application is : 1,3 1,23 1,223 1,2223 1,22222 1,222223 Is there something wrong ? In my application I must use five decimal digits and this round method. Regards Andrea

                    G Offline
                    G Offline
                    ghle
                    wrote on last edited by
                    #9

                    Use integer math with normalized integers and there is no problem. Added bonus - it's a gazillion time faster than floating point math. Divide by 10^5 before displaying to humans.

                    CICCIOLO69 wrote:

                    In my application I must use five decimal digits and this round method.

                    Teacher evidently wants you to think a little, knowing the problem exists.

                    Gary

                    1 Reply Last reply
                    0
                    • S Stuart Dootson

                      Rather than try to compute Delta, use Double.Epsilon instead - then you could just do Num + Delta.

                      S Offline
                      S Offline
                      supercat9
                      wrote on last edited by
                      #10

                      Stuart Dootson wrote:

                      Rather than try to compute Delta, use Double.Epsilon instead - then you could just do Num + Delta.

                      The smallest delta value for a given number will only equal Double.Epsilon if the number is very close to zero. In practice, it will always be equal to either the number divided by a particular power of two, or (if that division yields zero) Double.Epsilon; any assumption about the power of two in question, however, may break portability if future machines support higher-precision numerics.

                      1 Reply Last reply
                      0
                      • C CICCIOLO69

                        I'll try to explain : look this example : Module Module1 Sub Main() Dim num AsDouble = 1.25 Console.WriteLine(Math.Round(num, 1, MidpointRounding.AwayFromZero)) num = 1.225 Console.WriteLine(Math.Round(num, 2, MidpointRounding.AwayFromZero)) num = 1.2225 Console.WriteLine(Math.Round(num, 3, MidpointRounding.AwayFromZero)) num = 1.22225 Console.WriteLine(Math.Round(num, 4, MidpointRounding.AwayFromZero)) num = 1.222225 Console.WriteLine(Math.Round(num, 5, MidpointRounding.AwayFromZero)) num = 1.2222225 Console.WriteLine(Math.Round(num, 6, MidpointRounding.AwayFromZero)) EndSub End Module The output of this sample console application is : 1,3 1,23 1,223 1,2223 1,22222 1,222223 Is there something wrong ? In my application I must use five decimal digits and this round method. Regards Andrea

                        T Offline
                        T Offline
                        Thomas Stockwell
                        wrote on last edited by
                        #11

                        The Round method does not use what most of the community expects the Round method to use with regards to its function. The reason being is because the Round method rounds to the nearest even integer, in a link following you will see it is termed: the bankers method. The Round method has two options: MidpointRounding.ToEven or MidpointRounding.AwayFromZero. Neither of these is exactly what a user may want to see. You may find a better here[^], at this URL (found by google) their is a custom function that should round based on what most of the community expects. I have no idea why Microsoft chose non-standard forms of the Round function.

                        Regards, Thomas Stockwell Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning. Visit my homepage Oracle Studios Discounted or Free Software for Students: DreamSpark - downloads.channel8.msdn.com MSDN Academic Alliance - www.msdnaa.com

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups