locked
Error converting double to unsigned __int64 RRS feed

  • Question

  • I'm seeing a problem in converting a double to an unsigned __int64.  If the double is greater than the maximum for a signed __int64, the conversion returns the wrong value.

    For example:

    {
        double d;
        unsigned __int64 num = 0xa000000000000000;

        printf("unsigned __int64 = %#I64x\n",num);
        d = (double)num;
        printf("To double        = %e\n",d);
        num = (unsigned __int64)d;
        printf("From double      = %#I64x\n\n",num);
    }

    Produces:

    unsigned __int64 = 0xa000000000000000    // Correct
    To double        = 1.152922e+019         // Correct
    From double      = 0x8000000000000000    // WRONG

    Is there a fix for this?

     

    Thursday, February 23, 2006 8:51 PM

Answers

  • This is actually a roundoff error.

    There is no conversion from an unsigned int __int64 to a double, only  signed __int64 to double. The first conversion was lossy since doubles can only hold 52 bits of precision. 

    The extreme negative [0x8000...n-zeros] is as close as you can get to representing the ideal smaller number [0x8000...m-zeros] where n<m, or in this case the ideal smaller number being represented in (double)num.

    I don't see a fix here.

    Thursday, February 23, 2006 9:50 PM
  • Intersesting.  If your code emits a warning under a different Microsoft compiler version, then you should open a bug against VS 2005 (is that what you're using) and someone from Microsoft can respond.

    Brian

     

    Thursday, February 23, 2006 10:07 PM

All replies

  • This is actually a roundoff error.

    There is no conversion from an unsigned int __int64 to a double, only  signed __int64 to double. The first conversion was lossy since doubles can only hold 52 bits of precision. 

    The extreme negative [0x8000...n-zeros] is as close as you can get to representing the ideal smaller number [0x8000...m-zeros] where n<m, or in this case the ideal smaller number being represented in (double)num.

    I don't see a fix here.

    Thursday, February 23, 2006 9:50 PM
  • There used to not be a conversion, and the compiler would complain about it.  There is clearly a conversion now from unsigned __int64 to double: the second line of output from my sample shows the correct answer.  I'm not worried about the loss of precision, I'm concerned that the code which is used to convert from double to unsigned __int64 (_ftol2) is returning an error for any input value greater than signed max, rather than an error for any input value greater than unsigned max.

     

    Thursday, February 23, 2006 10:04 PM
  • Intersesting.  If your code emits a warning under a different Microsoft compiler version, then you should open a bug against VS 2005 (is that what you're using) and someone from Microsoft can respond.

    Brian

     

    Thursday, February 23, 2006 10:07 PM
  • I ran into this problem today.  I tried Jim's example on Visual Studio 2008 and got the same result for a Win32 build, so no fix there yet.  Then, I went to a 64-bit box and ran a 64-bit build of it, and it did the math correctly (using the cvttsd2si instruction rather than calling out to _ftol2 as in the 32-bit case). 

     

    Did someone actually enter a bug on this, and if so, have we heard from Microsoft as to whether they consider this to be a bug?

     

    Thanks,

     

    Eric

     

    Tuesday, September 18, 2007 6:53 PM