locked
Issues with Math functions in Visual Studio Versions RRS feed

  • Question

  • #include "string.h"
    #include "math.h"

    int main ()
    {
       
    double result = (double)sqrt(2.3456F);
       
    unsigned char data[8]; //holds the bytes of the result

        memmove
    (data,&result,8);
       
    for(int i=0;i<8;i++)
            printf
    ("%d\n",data[i]);
       
    return 0;
    }

    The above same code convert the sqrt() result to double and then stores in another double variable. Here the data holds the binary representation of the floating point number result.The same code when run on Visual C++ 6.0 and Visual C++ 2010 gives different results. Why is this so?

    and one more thing is If the result had been a float then Visual C++ 6.0 and Visual C++ 2010 are giving the same value for the result.

    Can any body sort out this??

    Output with result variable being double::

    with Visual C++ 6.0

    byte representation of result variable-data::

    [0] 196 'Ä'
    [1] 12 ''
    [2] 25 ''
    [3] 254 'þ'
    [4] 42 '*'
    [5] 129 ''
    [6] 248 'ø'
    [7] 63 '?'

    with Visual C++ 2010

    data::

        [0] 0   unsigned char
       
    [1] 0   unsigned char
       
    [2] 0   unsigned char
       
    [3] 0   unsigned char
       
    [4] 43 '+'  unsigned char
       
    [5] 129 ''  unsigned char
       
    [6] 248 'ø' unsigned char
       
    [7] 63 '?'  unsigned char

    Output with result variable being float::

    with Visual C++ 6.0

        [0] 88 'X'  
       
    [1] 9 ' '  
       
    [2] 196 'Ä'
       
    [3] 63 '?'  

    with Visual C++ 2010

    I got the same binary value for result variable as above.


    Mahesh
    Wednesday, January 11, 2012 11:43 AM

All replies

  • It seems VC6 handles the sqrt different to VC2010. VC6 takes the double version of sqrt, in your particualr example VC2010 takes the float version in my opinion.

    If you change the line with your calculation to:

    double result = (double)sqrt(2.3456);

    the result seems a double value and not a (to double) casted float value.
    Wednesday, January 11, 2012 11:53 AM
  • No,I have checked VC6 is using float version of sqrt only.But one thing i observed is VC2010 does not have float versions of the math functions.So VC2010 might be using double version of sqrt and VC6 might be using float version of sqrt. Could that be reason for this difference in the results for the same code on different versions??Correct me if i am wrong.
    Mahesh
    Wednesday, January 11, 2012 12:02 PM
  • I have a few things to point out..

    sqrt(2.3456F);  defines a 4 byte single precision float, this gets converted to a double that the c library function sqrt accepts.  Result is a double 8 byte number.  A better way to tell the compiler what you want is to include types:

    const double n = 2.3456;  // now this is a true double 

    Another thing to check would be the compiler setting for "Floating Point Model" on both versions, to check for differences.  Clearly from you message, you got a float, 4 byte version of the sqrt function.  That should have required using the sqrtf function.  I would also try the cmath.h library for any differences also, as this would be a c++ conforming library.


    -QuickC
    Wednesday, January 11, 2012 9:34 PM
  • Mahesh Punna wrote:
    >
    >#include "string.h"
    >#include "math.h"
    >
    >int main ()
    >{
    >    double result = (double)sqrt(2.3456F);
    >    unsigned char data[8]; //holds the bytes of the result
    >
    >    memmove(data,&result,8);
    >    for(int i=0;i<8;i++)
    >        printf("%d\n",data[i]);
    >    return 0;
    >}
    >
    >The above same code convert the sqrt() result to double and then stores
    >in another double variable.
     
    Nope, that's not what happens.  In VC 2008 and 2010, your program calls the
    function sqrtf, which takes a float and returns a float.  Check the source
    for <math.h>.  There is an inline overload of sqrt that takes a float, and
    calls sqrtf instead.
     
    The float-to-double conversion merely adds zeros.  That explains your
    result.
    --
    Tim Roberts, timr@probo.com
    Providenza & Boekelheide, Inc.
     

    Tim Roberts, VC++ MVP Providenza & Boekelheide, Inc.
    Friday, January 13, 2012 7:36 AM
  • @Tim Rpberts: I have checked in VC6 and VC2010 have same type of calls for sqrt() and sqrtf() in math.h

    Mahesh
    Friday, January 13, 2012 10:43 AM
  • Mahesh Punna wrote:
    >
    >@Tim Rpberts: I have checked in VC6 and VC2010 have same type of calls for sqrt() and sqrtf() in math.h
     
    No, not exactly.  In VC6, the inline overload for (float)sqrt(float) is
    only defined if the symbol _MSC_EXTENSIONS is not defined.  By default,
    that symbols IS defined.  If you check the compiled code (/FAsc), you'll
    see that the compiler immediately promotes your float constant to a double,
    then calls the original sqrt that takes a double and returns a double.
     
    If you #undef _MSC_EXTENSIONS, the code in VC6 is similar to VC2010 but
    again not identical, and the difference is subtle.  The top-level code
    basically does this:
        FLD     DWORD (load your constant as a float)
        FSTP    DWORD (push your constant on the stack as a float)
        CALL    ?sqrt@@YAMM@Z
        FSTP    QWORD (store double result in your buffer)
     
    ?sqrt@YAMM@Z eventually calls the _sqrtf function in both versions.  In
    VC2010, the _sqrtf function does this:
        FLD DWORD      (load argument as a float)
        FSTP QWORD     (store it as a double)
        FSQRT          (do double-to-double sqrt)
        FSTP DWORD     (store only the top 32-bits in memory)
        FLD QWORD      (load that float as a double)
    It promotes the float to a double, does the square root, then stores the
    double result but reloads as a float.  So, the top of the stack gets
    truncated to a float, and the FSTP in the top-level code gets a float value
    with the bottom 32 bits zero.
     
    In VC6, the _sqrtf function does this:
        FLD DWORD
        FSTP QWORD
        FSQRT
        FST DWORD
    It stores the double result, but it leaves the top of the stack at full
    precision.  By the time it gets back to the top-level, the top of stack
    still has all 64-bits of precision.
     
    So, I think you could argue this was a bug in VC6 that has since been
    corrected.
    --
    Tim Roberts, timr@probo.com
    Providenza & Boekelheide, Inc.
     

    Tim Roberts, VC++ MVP Providenza & Boekelheide, Inc.
    Saturday, January 14, 2012 11:50 PM
  • @Tim Roberts,Thanks for your reply.What would suggest me to make math function sqrt to have the same in both VC6 and VC2010.

    Shall I convert the float to double and before calling sqrt() function in VC2010?? (i.e sqrt((double) float-variable ))

    Or  any possible way to make VC2010 sqrt() produces the same results as VC6 without making any changes to VC6 code?


    Mahesh
    Monday, January 16, 2012 5:19 AM
  • Mahesh Punna wrote:
    >
    >@Tim Roberts, Thanks for your reply.What would suggest me to make
    >math function sqrt to have the same in both VC6 and VC2010.
     
    In what universe would it possibly matter?
     
    >Shall I convert the float to double and before calling sqrt()
    >function in VC2010?? (i.e sqrt((double) float-variable ))
     
    That should give you the same result, but it would have been quicker to try
    it yourself.
    --
    Tim Roberts, timr@probo.com
    Providenza & Boekelheide, Inc.
     

    Tim Roberts, VC++ MVP Providenza & Boekelheide, Inc.
    • Proposed as answer by Fredrick_V Thursday, March 22, 2012 9:02 PM
    Tuesday, January 17, 2012 4:50 AM