This question already has an answer here:
- Representing integers in doubles 5 answers
My question is whether all integer values are guaranteed to have a perfect double representation.
Consider the following code sample that prints "Same":
// Example program
#include <iostream>
#include <string>
int main()
{
int a = 3;
int b = 4;
double d_a(a);
double d_b(b);
double int_sum = a + b;
double d_sum = d_a + d_b;
if (double(int_sum) == d_sum)
{
std::cout << "Same" << std::endl;
}
}
Is this guaranteed to be true for any architecture, any compiler, any values of a
and b
? Will any integer i
converted to double
, always be represented as i.0000000000000
and not, for example, as i.000000000001
?
I tried it for some other numbers and it always was true, but was unable to find anything about whether this is coincidence or by design.
Note: This is different from this question (aside from the language) since I am adding the two integers.
Disclaimer (as suggested by Toby Speight): Although IEEE 754 representations are quite common, an implementation is permitted to use any other representation that satisfies the requirements of the language.
The doubles are represented in the form
mantissa * 2^exponent
, i.e. some of the bits are used for the non-integer part of the double number.The part in the fraction can also used to represent an integer by using an exponent which removes all the digits after the dot.
E.g. 2,9979 · 10^4 = 29979.
Since a common
int
is usually 32 bit you can represent allint
s as double, but for 64 bit integers of course this is no longer true. To be more precise (as LThode noted in a comment): IEEE 754 double-precision can guarantee this for up to 53 bits (52 bits of significand + the implicit leading 1 bit).Answer: yes for 32 bit ints, no for 64 bit ints.
(This is correct for server/desktop general-purpose CPU environments, but other architectures may behave differently.)
Practical Answer as Malcom McLean puts it: 64 bit doubles are an adequate integer type for almost all integers that are likely to count things in real life.
For the empirically inclined, try this:
Subquestion: Regarding the question for fractional differences. Is it possible to have a integer which converts to a double which is just off the correct value by a fraction, but which converts back to the same integer due to rounding?
The answer is no, because any integer which converts back and forth to the same value, actually represents the same integer value in double. For me the simplemost explanation (suggested by ilkkachu) for this is that using the exponent
2^exponent
the step width must always be a power of two. Therefore, beyond the largest 52(+1 sign) bit integer, there are never two double values with a distance smaller than 2, which solves the rounding issue.You have 2 different questions:
That was already answered by other people (TL;DR: it depends on the precision of
int
anddouble
).Your code adds two
int
s and then converts the result to double. The sum ofint
s will overflow for certain values, but the sum of the two separately-converteddouble
s will not (typically). For those values the results will differ.The short answer is "possibly". The portable answer is "not everywhere".
It really depends on your platform, and in particular, on
double
int
For platforms using IEEE-754 doubles, it may be true if
int
is 53-bit or smaller. For platforms whereint
is larger thandouble
, it's obviously false.You may want be able to investigate the properties on your runtime host, using
std::numeric_limits
andstd::nextafter
.No. Suppose you have a 64-bit integer type and a 64-bit floating-point type (which is typical for a
double
). There are 2^64 possible values for that integer type and there are 2^64 possible values for that floating-point type. But some of those floating-point values (in fact, most of them) do not represent integer values, so the floating-point type can represent fewer integer values than the integer type can.The answer is no. This only works if
int
s are 32 bit, which, while true on most platforms, isn't guaranteed by the standard.The two integers can share the same double representation.
For example, this
will print
I.e. both 2397083434877565865 and 2397083434877565864 will convert to the same
double
.Note that I used
int64_t
here to guarantee 64-bit integers, which - depending on your platform - might also be whatint
is.