3 Replies Latest reply: Feb 2, 2012 11:06 PM by 858326 RSS

    Abnormal behaviour of float.

    858326
      Hi All,

      I have different output when trying to cast float/double to integer.

      I know that doing such a conversion is illegal, but the (legacy) code is written like that, and now we are trying to make the code compliant with C+ standards.+

      test.cc
      #include<iostream>
      using namespace std;
      
      int main()
      {
          float f = 0.9972222;
          short fx = (f*1440);
          cout << "Using float\t - " << fx << endl;
          double d =  0.99722222222222;
          short dx = (d*1440);
          cout << "Using double\t - " << dx << endl;
      
          return 0;
      }
      The environment details and the output.
      $ cat /etc/redhat-release
      Red Hat Enterprise Linux Server release 5.4 (Tikanga)
      
      $ uname -a
      Linux n320.ibsplc.com 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
      
      # compile with CC
      $ CC -m32 -g -o test test.cc
      $ ./test
      Using float      - 1436
      Using double     - 1435
      
      # compile with g++
      $ g++ -Wall -m32 -g -o test test.cc
      test.cc: In function ‘int main()’:
      test.cc:7: warning: converting to ‘short int’ from ‘float’
      test.cc:10: warning: converting to ‘short int’ from ‘double’
      $ ./test
      Using float      - 1435
      Using double     - 1435
      I am getting different values when we trying to use float and double with CC whereas the values are same with g++

      i also compared the output of different numbers (up-to 4 digit precision).

      When using double the output is same in both CC and g++.
      When using float, for some cases (like the one mentioned above) CC gives one value more ( float : 1436...double : 1435 ) whereas g++ gives same value ( float : 1435...double : 1435 )

      Can anyone explain why this happens with CC ?

      Any inputs would be of great help.


      Thanks & Regards,
      Sreekar.

      Edited by: 855323 on Feb 2, 2012 8:54 PM
        • 1. Re: Abnormal behaviour of float.
          Darryl Gove-Oracle
          Its to do with promotion to double. Here's what I think is happening:

          0.9972222 * 1440 =1435.99968
          A single precision variable can hold about 7 digits so the multiply does a rounding at the '6' digit, and this makes the result 1436.

          If the whole calculation is done as a double precision value, then you end up with many more digits of precision.

          When the code converts to int, it truncates at the decimal point. So 1435.9 becomes 1435.

          So gcc is doing the computation as double precision even though it is a single precision calculation, studio is doing it as specified.

          So the question is which is the desired answer?

          If you want to make it consistent, I'd suggest adding (double) to force the computation to be evaluated as a double precision:
          short fx = ((double)f*1440);

          On the other hand you might want to round the values to the nearest int rather than truncate them:
          short fx = (f*1440+0.5);
          [Although there might be some values which round up for float and down for double... you'd need a numeric analysis to figure that out.]

          Regards,

          Darryl.
          • 2. Re: Abnormal behaviour of float.
            Darryl Gove-Oracle
            g++ gives the same behaviour as studio:

            #include<stdio.h>

            int main()
            {
            float f = 0.9972222;
            short fx = (f*1440);
            printf("Using float %i %20.18f\n",fx,(float)(f*1440));
            double d = 0.99722222222222;
            short dx = (d*1440);
            printf("Using double %i %20.18f\n",dx,(double)(d*1440));

            return 0;
            }

            $ g++ -v
            Using built-in specs.
            Target: sparc-sun-solaris2.10
            Configured with: ../gcc-4.3.2-src/configure prefix=/pkg/gnu enable-languages=c++,fortran with-cpu=ultrasparc enable-threads=posix enable-shared with-gmp=/pkg/gnu --program-suffix=-4.3.2-5.10
            Thread model: posix
            gcc version 4.3.2 (GCC)

            $ g++ t1.c
            ./a.out
            Using float 1436 1436.000000000000000000
            Using double 1435 1435.999999999996816769

            $ CC t1.c
            $ ./a.out
            Using float 1436 1436.000000000000000000
            Using double 1435 1435.999999999996816769

            Regards,

            Darryl.
            • 3. Re: Abnormal behaviour of float.
              858326
              Hi Darryl,

              Thank you for your inputs.

              We are using -m32 in the compilation.
              # without -m32 flag
              $ g++ -Wall -g -o test test.cc
              test.cc: In function ‘int main()’:
              test.cc:8: warning: converting to ‘short int’ from ‘float’
              test.cc:11: warning: converting to ‘short int’ from ‘double’
              $ ./test
              Using float      - 1436
              Using double     - 1435
              
              # with -m32 flag
              $ g++ -m32 -Wall -g -o test test.cc
              test.cc: In function ‘int main()’:
              test.cc:8: warning: converting to ‘short int’ from ‘float’
              test.cc:11: warning: converting to ‘short int’ from ‘double’
              $ ./test
              Using float      - 1435
              Using double     - 1435
              Without that the values obtained with both CC and g++ are same.

              I think its time to chase the analysts to know what value they need as per the business.


              Thanks & Best Regards,
              Sreekar

              Edited by: 855323 on Feb 2, 2012 9:06 PM