News for hackers. Stuff that matters.
Re:Issues with porting C++ code to a 64-bit platform by 16s on Monday April 01, 2013 @02:55PM (#5475104)
But while trying to store a 64-bit integer in double the exact value can be lost (see picture 1).

I've seen that first hand. In fact, I wrote code to fix it. The guy who wrote the code, still did not get it... 64 bits is 64 bits he said, right... well yes, but that's not the issue here. When you have an int that is say 56 bits in size and you put it in a double that is 64 bits... see what happens:

#include <iostream>

#include <boost/integer.hpp>

int main()

{

    boost::uint64_t too_big = 72057594037927936;

    double wont_fit = too_big;

    std::cout << too_big << "\n";

    std::cout << wont_fit << "\n";

    return 0;
}

./a.out

72057594037927936

7.20576e+16

The maddening part about this is that it's hit or miss. Smaller numbers fit just fine:

#include <iostream>

#include <boost/integer.hpp>

int main()

{

    boost::uint64_t not_too_big = 281234;

    double will_fit = not_too_big;

    std::cout << not_too_big << "\n";

    std::cout << will_fit << "\n";

    return 0;
}

./a.out

281234

281234

Finding and fixing bugs like this will cause ulcers.

Re:Issues with porting C++ code to a 64-bit platform by thwest on Monday April 01, 2013 @03:33PM (#5475325)
Your first example works just fine with increased output precision. https://ideone.com/GtMDit A slightly larger number shows the discrepancy: https://ideone.com/WPtpX4
Re:Issues with porting C++ code to a 64-bit platform by Arelius on Monday April 01, 2013 @03:24PM (#5475280)
> 64 bits is 64 bits he said, right... well yes

That's the problem right there. 64 bits is not always 64 bits. While a 64 bit int gives you a 64 bit number (Actually a 63 bit number and a 1 bit sign flag). An IEEE double precision float only gives you a 52 bit number, and a separate 11 bit number as an exponent. So the problem is that declaring that 64 bits is 64 bits is actually precisely the issue here.

Re:Issues with porting C++ code to a 64-bit platform by MichaelSalib on Monday April 01, 2013 @03:36PM (#5475348)
Actually a 63 bit number and a 1 bit sign flag

Not true. Modern architectures use 2s-complement rather than an explicit sign bit to represent integers. If you use a sign bit, there are two different zeros (positive and negative) but the range of positive numbers is exactly as large as the range of negative numbers. With 2s-complement, there's only one zero and the range of negative numbers is larger (by one) than the range for positive numbers.

Re:Issues with porting C++ code to a 64-bit platform by dschatz on Monday April 01, 2013 @03:55PM (#5475467)
In 2s complement, the most significant bit is the sign bit. In fact all valid C integer representations have a sign bit.
Re:Issues with porting C++ code to a 64-bit platform by cube13 on Monday April 01, 2013 @03:57PM (#5475485)
Signed integer representations. Unsigned ints do not, and you're given the full range of the integer as valid data.
Re:Issues with porting C++ code to a 64-bit platform by dschatz on Monday April 01, 2013 @04:09PM (#5475566)
Yes you're right. I should have been more specific that all signed integers have a sign bit.
Re:Issues with porting C++ code to a 64-bit platform by MichaelSalib on Monday April 01, 2013 @04:36PM (#5475749)
This is wrong.

Take an integer value x. Flip the sign bit. Do you now have the value -x? On a 2s complement architecture, you do not. In 2s complement, you have to flip all the bits and add one to get -x.

Re:Issues with porting C++ code to a 64-bit platform by dschatz on Thursday April 04, 2013 @10:02AM (#5492679)
Sign bit means one bit represents the sign of the integer which is the case with the most significant bit in 2s complement.

If you flip the sign bit, the sign changes. It does not mean that if you flip the sign, the value is negated.

Re:Issues with porting C++ code to a 64-bit platform by to3m on Monday April 01, 2013 @04:20PM (#5475630)
I think his point is that changing a sign bit doesn't affect the absolute value, just its sign. A sign bit has no value itself - it's just a flag. If the representation has a sign bit, you'd have a negative zero.

But the top bit in 2s complement has a value - it's just a negative one (that's large enough to make any value with it set negative). That's not a sign bit! If you change it, the absolute value most definitely changes, and quite substantially.

Re:Issues with porting C++ code to a 64-bit platform by xentronium on Monday April 01, 2013 @04:06PM (#5475545)
This is a technicality. Leftmost bit still denotes a sign and modulo of the number is still capped at n-1 bits.
Re:Issues with porting C++ code to a 64-bit platform by MichaelSalib on Monday April 01, 2013 @04:33PM (#5475728)
The differences between the representations matter. In 2s complement, -INT_MIN is not INT_MAX; in fact, -INT_MIN is undefined and a C compiler is justified in deleting all your code if you ever cause it to calculate -INT_MIN.

I tell you what: if you think modern architectures use an explicit sign bit to represent integers, how do you explain the fact that INT_MAX+1==-INT_MIN? If there's a sign bit, how could you possibly represent more negative integers than positive integers?

Re:Issues with porting C++ code to a 64-bit platform by Arelius on Monday April 01, 2013 @11:58PM (#5477617)
Are you arguing that given such, I have more than 63 bits for the number, or do you just have a problem with the usage of the words "sign flag"?
Re:Issues with porting C++ code to a 64-bit platform by peripetylabs on Monday April 01, 2013 @05:09PM (#5475947)
One way to avoid loss of precision in the conversion is to check if the number of digits in the integer is larger than the constant DBL_DIG (defined in <cfloat>) -- numbers with less digits than that constant can be safely converted to the 'double' type and back.
Re:Issues with porting C++ code to a 64-bit platform by thwest on Monday April 01, 2013 @05:53PM (#5476199)
Note that DBL_DIG is the number of decimal digits that can be a 9. If the max integral value storable in a double is 4,000,000, DBL_DIG would only be 6. It is a conservative limit.