17

the code:

#iclude <math.h>

int main(){
double somenumber = pow(2, 1000);
printf("%lf\n", somenumber);
return 0;
}

i get this huge number: 10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

This is obviously to big for double. How it's working?

David Hammen
  • 32,454
  • 9
  • 60
  • 108
0xbadc0de
  • 3,805
  • 3
  • 22
  • 14
  • 24
    I'm glad you can glance at a number and tell whether it's too big to fit in a double. I can't. – Ben Voigt Sep 10 '11 at 13:23
  • 2
    I can except for borderline cases, if I'm looking at it on a terminal where I know the width of a line in columns... :-) – R.. GitHub STOP HELPING ICE Sep 10 '11 at 13:29
  • floating point means the location of the `.` point floats (c.f. fixed point) For double the point can float by as much as 2^-1022 to 2^1023. However, the hint is in the name. – Peter Lawrey Sep 10 '11 at 13:43
  • @Peter Lawrey: 2^-1074 is the lower limit, not 2^-1022. Numbers between 2^-1074 and 2^-1022 are representable in the IEEE 754 format, but as unnormalized numbers. – David Hammen Sep 10 '11 at 14:03
  • @David Hammen, True, but the exponent is never below 2^-1022 – Peter Lawrey Sep 10 '11 at 14:05
  • 2
    *"This is obviously too big for double"* - No, it isn't (especially not *obviously* ;)) – Christian Rau Jan 28 '13 at 17:07
  • One way to get a feeling for the actual precision of floating-point numbers is to compare `somenumber` to the immediately preceding and following representable numbers, using the [`nextafter()`](http://linux.die.net/man/3/nextafter) function. Try printing `nextafter(somenumber, 0.0)` and `nextafter(somenumber, 2.0*somenumber)`. You'll see that only the first 16 or so digits are the same. But all three numbers are integer multiples of powers of `2.0`. – Keith Thompson Jan 28 '13 at 22:54

3 Answers3

33

This is obviously to big for double. How it's working?

21000 is within the range of numbers that can be represented by a double. So this number obviously is not too big for a double.

I suspect that what you mean by "too big" is that the number of digits printed is much greater than the 16 or so digits that can be stored in a double. There's nothing wrong with asking a computer to print more than 16 decimal digits. What's wrong is assuming that those extra digits have any meaning.

In this particular case, the printed number is exactly correct. That's because the computer treats pow(2,some_int) specially. Powers of 2 can be represented exactly in a double. The algorithm used to compute the decimal representation of an exact integral value will give the exactly correct decimal representation.

Anything else, all bets are off. Change your program so it prints 3646 for example:

#include <math.h>
#include <stdio.h>

int main(){
  double somenumber = pow(3, 646);
  printf("%lf\n", somenumber);
  return 0;
}

It will still print a big long number, but only the first 16 or so digits will be correct.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • ok, i think i get it almost. the last qustion: that huge number, is it stored like powers of 2 in somenumber variable and it's the implementation of printf that computes the decimal representation of that number? Correct? – 0xbadc0de Sep 10 '11 at 14:05
  • 1
    @user938183 Yes, you are right. Numbers are just numbers in computer. But printf turns them into strings that can be printed on the screen – Haozhun Sep 10 '11 at 14:11
  • @user938183:Yes, `printf` computes the decimal representation -- at least on most computers. The IEEE floating point standard also allows for decimal rather than binary exponents. Most computers use the binary format. A lot of calculators use decimal exponents. – David Hammen Sep 10 '11 at 14:14
  • 3
    Yes, computing the decimal representation is part of `printf`, not an inherent property of the `double` variable's value. The value shown by `printf` is only required to be correct in the first `DECIMAL_DIG` places, even though 2^1000 has an exact representation as `double`. A good implementation will print the exact value, but doing so is non-trivial and fairly expensive in computation time and space. – R.. GitHub STOP HELPING ICE Sep 10 '11 at 14:14
  • Note - it is not a requirement of the C Standard that this number be representible exactly . But most systems use base 2 floating point. – M.M Jun 17 '21 at 01:35
13

double usually has 11bit for exp (-1022~1023 normalized), 52bit for fact and 1bit for sign. Thus it's simply not too large. For more explanation, see IEEE 754 on Wikipedia

Haozhun
  • 6,331
  • 3
  • 29
  • 50
  • 2^1000 needs 1000 bits to represent, how does what you wrote explain that ? – Itsik Sep 10 '11 at 13:20
  • 2
    @ltsik Normalized float number are saved as 1.xxxx * 2 ^ yyyyy. Where xxx is called fact part and yyyy called exp part. It's not exactly the number most of the case (when the number will repeat indefinitely in binary representation, just as 1/3 in decimal. Or it would not repeat indefinitely but simply won't fit into the allocated bits for xxxx). – Haozhun Sep 10 '11 at 13:21
  • 2
    @Itsik: In other words, floating point is the computer's way of doing scientific notation. 2^1000 does not require 1000 bits to represent it. The `double` stores 2^1000 by storing the base (2) and the exponent (1000). Clearly, storing a 2 and a 1000 takes much less than 1000 bits. – In silico Sep 10 '11 at 13:24
  • @ltsik: even 10^1000 would require 1000 digits to be represented in "normal" decimal form, still when written as mantissa*10^exponent it takes just 5 decimal digits. – Matteo Italia Sep 10 '11 at 13:25
  • Thanks, obviously I was not listening during my Numerical Analysis lectures – Itsik Sep 10 '11 at 13:25
  • 2
    @Itsik: You do, however, need 1000 bits if you want to be able to represent *every single integer* between 0 and (2^1000)-1. This is in contrast with floating-point types; the range of values that a `double` can represent is not contiguous. For example, you can't store `1/3` exactly in a `double`. – In silico Sep 10 '11 at 13:26
  • but why is it not working on pow(3,1000)? really don't get it. – 0xbadc0de Sep 10 '11 at 13:32
  • 1
    @user938183 3^1000 is beyond 1.111111111(52 binary ones)*2^1023 – Haozhun Sep 10 '11 at 13:33
  • 1
    @user939183: The maximum integer power of 3 that can be represented in a double is 3646. The IEEE 754 format that most computers use for doubles can only represent values between about 4.94066e-324 and 1.79769e+308. Anything with an absolute value less than the minimum is zero as far as your computer is concerned, anything greater the maximum is just infinity. – David Hammen Sep 10 '11 at 13:58
3

It is a power of two, and the floating point are essentially stored as (multiples of) powers of two.

Similarly, in decimal system, it shouldn't surprise you that it takes very little room to represent 101000 precisely, but such a concise notation would not be possible for large powers of other values, like 31000 = 1322070819480806636890455259752144365965422032752148167664920368226828597346704899540778313850608061963909777696872582355950954582100618911865342725257953674027620225198320803878014774228964841274390400117588618041128947815623094438061566173054086674490506178125480344405547054397038895817465368254916136220830268563778582290228416398307887896918556404084898937609373242171846359938695516765018940588109060426089671438864102814350385648747165832010614366132173102768902855220001.

UncleBens
  • 40,819
  • 6
  • 57
  • 90