Question

I read here and concluded that the minimum(absolute ...) value for double is 1.7e-308 but my code loops forever:

for (double d(-1.0); d <= 1.0; d+=1.7e-308)
{
}

Edit: I want to loop from -1.0 to 1.0 in the smallest possible increment.

Was it helpful?

Solution 2

TL;DR: the gap between the numbers that a computer is able to store in floating point numbers gets larger as the number gets larger. Your minimum number is only valid when the number is zero. At some point, trying to add such a small number does nothing as it can't represent such a small change in number.

This is because the gap between each representable floating point numbers is larger as your number increases in magnitude.

The difference between 1 and the closest representable smaller than 1 is about 1.11 × 10-16, much larger than the value that you're trying to add.

What happens is that a double is stored with one set of bits for the sign of the number, another to represent the number itself (as an unsigned integer) and a multiplier as an exponent of 2.

When you are near zero, the exponent is very small, making one change in the actual number stored less than if your exponent is much larger.

For example, (4 - 3) × 299 is obviously going to be larger than (4 - 3) × 2-99, which is what is basically happening.

When you start adding, you'll find that eventually, adding 1.7 × 10-308 does nothing as your current value is the closest representable value for the addition, which keeps going on and on in an infinite loop.

Note that this is only when the rounding mode is set to roundTiesToEven or roundTiesToAway, where they round to the nearest representable value, except when they are equally near.

If you have manually set the rounding mode to roundTowardPositive by calling std::fesetround with FE_UPWARD beforehand (as Marc Glisse noted), if you add any positive number (except zero), it would keep increasing. I think roundTowardNegative and roundTowardZero are self-explanatory.

BTW, even if you replace that with 1.11 × 10-16, you're still going to have to go through 18 014 398 509 481 984 (18 quadrillion) iterations before you finish. If you actually loop through each of the values between -1 and 1, that's 9 223 372 036 854 775 809 (9 quintillion) iterations. Good luck.

OTHER TIPS

In C++11/C99 you can use nextafter to get the next representable number.

#include <cmath>

for (double d(-1.0); d <= 1.0; d = std::nextafter(d, 1.0) )
{
}

Also if I did the math correctly there are approximately 10^18 representable values between -1 and 1.

With the reasonable assumption of 10^6 cycles per second it will take 32000 years to perform this computation.

I don't think the minimum value for double is 1.7e-308 it's probably more like -1.7 e308, 1.7e-308 is a really small number, but not a close number to negative infinity. It is a very small number close to 0.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top