Reputation: 21
I have a problem in printing a double
in C.
My code:
#include <stdio.h>
main() {
double n;
scanf("%lf", &n);
printf("%f", n);
}
input: 446486416781684178
output: 446486416781684160
Why does the number change ?
Upvotes: 1
Views: 8768
Reputation: 48042
Why does the number change?
It got rounded off, because type double
has finite precision.
We're used to roundoff happening to the right of the decimal point. If we write
double d = 0.123456789012345678;
printf("%.18f\n", d);
we are not too surprised if it prints
0.123456789012345677
Type double
has the equivalent of about 16 decimal digit's worth of precision (actually it's more complicated than that), so it definitely can't represent all 18 digits of that number 0.123456789012345678.
But your number 446486416781684178 also has 18 significant digits, so we can't be too surprised that it can't be represented exactly, either. In other words, roundoff can happen to the left of the decimal point, also.
Internally, type double
can represent numbers with 53 bits of precision. That means it can represent integers up to 253, or 9007199254740992, with perfect accuracy. But bigger than that — it just can't! It can represent 900...992, and it can represent 900...994, but if you try to do 900...993, it gets rounded back down to 900...992. If we look at the binary representations of these and nearby numbers, we can see why:
Decimal | Binary | Rep? |
---|---|---|
9007199254740990 | 11111111111111111111111111111111111111111111111111110 |
yes |
9007199254740991 | 11111111111111111111111111111111111111111111111111111 |
yes |
9007199254740992 | 100000000000000000000000000000000000000000000000000000 |
yes |
9007199254740993 | 100000000000000000000000000000000000000000000000000001 |
no |
9007199254740994 | 100000000000000000000000000000000000000000000000000010 |
yes |
Since we only have 53 bits of significance, for a 54-bit number like 9007199254740992 or 9007199254740994, the 54th bit has to be 0, which basically means we can only represent even numbers in that range. The 54-bit number 9007199254740993 ends with a 1 bit, so it can't be exactly represented, which I've indicated with a "no" in the "Rep" ("exactly representable") column.
When we get up to a 59-bit number like 446486416781684178, the last six bits have to be 0, which means we can only represent numbers which are a multiple of 26, or 64:
Decimal | Binary | Rep? |
---|---|---|
446486416781684160 | 1100011001000111101…001101010011110010110111000000 |
yes |
446486416781684161 | 1100011001000111101…001101010011110010110111000001 |
no |
... | ... | ... |
446486416781684177 | 1100011001000111101…001101010011110010110111010001 |
no |
446486416781684178 | 1100011001000111101…001101010011110010110111010010 |
no |
446486416781684179 | 1100011001000111101…001101010011110010110111010011 |
no |
... | ... | ... |
446486416781684223 | 1100011001000111101…001101010011110010110111111111 |
no |
446486416781684224 | 1100011001000111101…001101010011110010111000000000 |
yes |
Upvotes: 3
Reputation: 145297
The number changes because of the limited precision of the double
type. If you don't need floating point values, you could use type long long
which is defined to have at least 63 value bits and can represent the number in the question.
Note that it is highly unlikely that the output be 446486416781684160
, the printf("%f", n)
call should produce 446486416781684160.000000
. If your program does not produce 6 decimal places, your compiler and/or standard library are not conforming.
Also note that the main
function should be defined with an explicit return type of int
. The implicit int
style has been deprecated more than 20 years ago.
Here is a modified version:
#include <stdio.h>
int main() {
long long n;
if (scanf("%lld", &n) == 1) {
printf("%lld\n", n);
}
return 0;
}
Input: 446486416781684178
Output: 446486416781684178
Upvotes: 1
Reputation: 225387
The number you entered can't be represented exactly in a double
.
Typically, a double
is represented using IEEE754 double precision format. This format can hold up to 53 bits of precision. The value you entered requires 58 bits of precision. So what is stored is either the next or the previous representable value.
Upvotes: 5