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. Other Discussions
  3. Clever Code
  4. Type conversion strange bug

Type conversion strange bug

Scheduled Pinned Locked Moved Clever Code
help
12 Posts 5 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
    cybertone
    wrote on last edited by
    #1

    Yesterday I've caught a very strange bug float a = 81.1666641F; float b = 18F; float c = 6.3166666F; float d = (a - b) / c; int e = (int)((a - b) / c); int f = (int)d; Console.WriteLine(d); Console.WriteLine(e); Console.WriteLine(f); -------------------------- OUTPUT: 10.0 9 10

    M L 2 Replies Last reply
    0
    • C cybertone

      Yesterday I've caught a very strange bug float a = 81.1666641F; float b = 18F; float c = 6.3166666F; float d = (a - b) / c; int e = (int)((a - b) / c); int f = (int)d; Console.WriteLine(d); Console.WriteLine(e); Console.WriteLine(f); -------------------------- OUTPUT: 10.0 9 10

      M Offline
      M Offline
      mabo42
      wrote on last edited by
      #2

      It seems that for any reason the c#-compiler handles a, b and c in the line int e = (int)((a - b) / c); as they were doubles: double d = ((double)a - (double)b) / (double)c); -> 9.99999969804507 If you change the calculation of e: int e = (int)(float)((a - b) / c); then you get OUTPUT: 10 10 10 Very strange.

      E 1 Reply Last reply
      0
      • M mabo42

        It seems that for any reason the c#-compiler handles a, b and c in the line int e = (int)((a - b) / c); as they were doubles: double d = ((double)a - (double)b) / (double)c); -> 9.99999969804507 If you change the calculation of e: int e = (int)(float)((a - b) / c); then you get OUTPUT: 10 10 10 Very strange.

        E Offline
        E Offline
        Ed Poore
        wrote on last edited by
        #3

        mabo42 wrote:

        Very strange.

        But well documented, the more annoying one which seems to have no obvious explanation is trying to take the modulus of a floating-point number.  This caused big problems for me, ended up rewriting the calculations to use integers with a final scaling factor at the end.

        M 1 Reply Last reply
        0
        • E Ed Poore

          mabo42 wrote:

          Very strange.

          But well documented, the more annoying one which seems to have no obvious explanation is trying to take the modulus of a floating-point number.  This caused big problems for me, ended up rewriting the calculations to use integers with a final scaling factor at the end.

          M Offline
          M Offline
          mabo42
          wrote on last edited by
          #4

          Ed.Poore wrote:

          But well documented

          I feared it.:rolleyes:

          E 1 Reply Last reply
          0
          • M mabo42

            Ed.Poore wrote:

            But well documented

            I feared it.:rolleyes:

            E Offline
            E Offline
            Ed Poore
            wrote on last edited by
            #5

            :-D - one of the reasons why Fortran still has it's applications.

            M 1 Reply Last reply
            0
            • E Ed Poore

              :-D - one of the reasons why Fortran still has it's applications.

              M Offline
              M Offline
              mabo42
              wrote on last edited by
              #6

              Once more about "well documented": I've found this in the c# docs [^]: The following table shows the predefined implicit numeric conversions. Implicit conversions might occur in many situations, including method invoking and assignment statements. From To ... float double ...

              float a = 81.1666641F;
              float b = 18F;
              float c = 6.3166666F;

              float f = (a - b) / c; // here no implicit conversion occurs
              int i1 = (int)(f); // -> 10
              int i2 = (int)((a - b) / c); // -> 9, imlicit conversion to double, caused by the explicit conversion to int

              The doc is still correct (might = could be, but not have to), but I would not expect this behavior. Lessons learned!

              E D 2 Replies Last reply
              0
              • M mabo42

                Once more about "well documented": I've found this in the c# docs [^]: The following table shows the predefined implicit numeric conversions. Implicit conversions might occur in many situations, including method invoking and assignment statements. From To ... float double ...

                float a = 81.1666641F;
                float b = 18F;
                float c = 6.3166666F;

                float f = (a - b) / c; // here no implicit conversion occurs
                int i1 = (int)(f); // -> 10
                int i2 = (int)((a - b) / c); // -> 9, imlicit conversion to double, caused by the explicit conversion to int

                The doc is still correct (might = could be, but not have to), but I would not expect this behavior. Lessons learned!

                E Offline
                E Offline
                Ed Poore
                wrote on last edited by
                #7

                mabo42 wrote:

                Lessons learned!

                Yep, when in doubt use integers :->

                1 Reply Last reply
                0
                • M mabo42

                  Once more about "well documented": I've found this in the c# docs [^]: The following table shows the predefined implicit numeric conversions. Implicit conversions might occur in many situations, including method invoking and assignment statements. From To ... float double ...

                  float a = 81.1666641F;
                  float b = 18F;
                  float c = 6.3166666F;

                  float f = (a - b) / c; // here no implicit conversion occurs
                  int i1 = (int)(f); // -> 10
                  int i2 = (int)((a - b) / c); // -> 9, imlicit conversion to double, caused by the explicit conversion to int

                  The doc is still correct (might = could be, but not have to), but I would not expect this behavior. Lessons learned!

                  D Offline
                  D Offline
                  Daniel Grunwald
                  wrote on last edited by
                  #8

                  That's not the reason. Actually, there's no conversion to double here. The C# specification just says somewhere something like "floating point calculations may be run with greater precision than specified". The reason is that variables are typed float or double, but floating point values on the MSIL evaluation stack are typed "F", a platform-specific floating point type. float: 32-bit double: 64-bit "F": 80-bit (because that's what the floating point unit of x86 processors internally uses)

                  M 1 Reply Last reply
                  0
                  • D Daniel Grunwald

                    That's not the reason. Actually, there's no conversion to double here. The C# specification just says somewhere something like "floating point calculations may be run with greater precision than specified". The reason is that variables are typed float or double, but floating point values on the MSIL evaluation stack are typed "F", a platform-specific floating point type. float: 32-bit double: 64-bit "F": 80-bit (because that's what the floating point unit of x86 processors internally uses)

                    M Offline
                    M Offline
                    mabo42
                    wrote on last edited by
                    #9

                    Hi Daniel, may be, I'm a bit on the slow side, but why the difference:

                    int i1 = (int) ((a - b) / c); // -> 9
                    int i2 = (int)(float)((a - b) / c); // -> 10

                    D 1 Reply Last reply
                    0
                    • M mabo42

                      Hi Daniel, may be, I'm a bit on the slow side, but why the difference:

                      int i1 = (int) ((a - b) / c); // -> 9
                      int i2 = (int)(float)((a - b) / c); // -> 10

                      D Offline
                      D Offline
                      Daniel Grunwald
                      wrote on last edited by
                      #10

                      int i1 = (int) (9.9999999999999); // -> 9
                      int i2 = (int)(float)(9.9999999999999); // -> 10

                      double has 15 significant decimal digits, float only about 7. When casting a value of type F (remember, 80-bit) to int, the digits after the decimal point are truncated. But when casting a value of type F to float, it is rounded to the next value. Simple rule: don't trust floating-point numbers. Never compare them for equality without rounding because possible errors in the calculation can created undefined results - e.g. in the set of floating point numbers, a/b is not always equal to (2*a)/(2*b). Never cast them to int without rounding if you want defined results for numbers equal to a whole integer (remember, there's no such thing as a floating point value equal to a whole integer if it came out of a calculation - it often works, but doesn't always have to)

                      M 1 Reply Last reply
                      0
                      • D Daniel Grunwald

                        int i1 = (int) (9.9999999999999); // -> 9
                        int i2 = (int)(float)(9.9999999999999); // -> 10

                        double has 15 significant decimal digits, float only about 7. When casting a value of type F (remember, 80-bit) to int, the digits after the decimal point are truncated. But when casting a value of type F to float, it is rounded to the next value. Simple rule: don't trust floating-point numbers. Never compare them for equality without rounding because possible errors in the calculation can created undefined results - e.g. in the set of floating point numbers, a/b is not always equal to (2*a)/(2*b). Never cast them to int without rounding if you want defined results for numbers equal to a whole integer (remember, there's no such thing as a floating point value equal to a whole integer if it came out of a calculation - it often works, but doesn't always have to)

                        M Offline
                        M Offline
                        mabo42
                        wrote on last edited by
                        #11

                        Many thanks for the detailed explanation, i've got it.

                        1 Reply Last reply
                        0
                        • C cybertone

                          Yesterday I've caught a very strange bug float a = 81.1666641F; float b = 18F; float c = 6.3166666F; float d = (a - b) / c; int e = (int)((a - b) / c); int f = (int)d; Console.WriteLine(d); Console.WriteLine(e); Console.WriteLine(f); -------------------------- OUTPUT: 10.0 9 10

                          L Offline
                          L Offline
                          Lost User
                          wrote on last edited by
                          #12

                          Seems to me you are running your program on original Pentium (remember - the one having problems with floating point operations) :laugh:

                          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