Mahesh
Mahesh

Reputation: 169

Issues with Math functions in Visual Studio versions

#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.

Upvotes: 0

Views: 751

Answers (1)

Lol4t0
Lol4t0

Reputation: 12547

Well, those 2 double values are almost the same. First, you should understand how real numbers are represented in memory: http://en.wikipedia.org/wiki/Double-precision_floating-point_format

You can see, that first bytes of data, that a differ, just an lest significant part of fraction. Now lets make an experiment and study, what values we get for 2 numbers: one calculated from sqrt, second replaces first 4 bytes with 0. Lets print out double result as a number, fraction and bytes represenation

void show(double result)
{
    unsigned char * data = (unsigned char*)&result;
    unsigned long long fraction = *(unsigned long long int*)&result;

    fraction = fraction & 0xFFFFFFFFFFFFF;//52-bit mask!
    printf("result: %8f, with fraction %4lld. ", result, fraction);
    for(int i=0;i<8;i++)
        printf("%2X ",data[i]);
    printf("\n");
}

int main ()
{
    double result = (double)sqrt(2.3456F);
    show(result);
    unsigned char * data = (unsigned char*)&result;
    memset(data, 0, 4);
    show(result);
    return 0;
}

For me output is

result: 1.531535, with fraction 2393821627440998. 66 5F C2  7 2B 81 F8 3F
result: 1.531535, with fraction 2393821497262080.  0  0  0  0 2B 81 F8 3F

As we can see, result is the same in both cases. The thing is that when exponent such a big value, changes in its lest significant bits does not produce any real change of the whole number.

Ok, why those values differ, while they are result of same calculation? It's because compiler. Different compilers produces slightly different code that produces slightly different result. But you should consider those 2 values same

EDIT: exact results of such a behavior Well, you originally had a float number which gives you 23-bits precision. You calculated sqrt on that value and get float value that still has 23-bits precision. Than you converted it to double, that has 52-bits precision. So, you tried to extend precision, but you had no enough information to do it correctly, that is why you finished with double that still has float precision. And all bits lesser significant that 23rd get random values. If you replace

(double)sqrt(2.3456F)

with

sqrt(2.3456)

you will get same result with both compilers, because you will use double- precision version of sqrt

Upvotes: 3

Related Questions