2

For this code segment

double count = 0.0;
while( count != 1.0)
{count += 1.0/3;}

I was wondering what parts of (IEEE 754) would cause count 3: to be 1.0 instead of .9999999999999999. I realize that the general reason would be rounding due to an infinite number of binary digits but if anyone could go into more detail to explain the (IEEE 754) specifics behind this I would appreciate it.

  • What kind of specifics are you looking for? You seem to have summed it up nicely already. – Scott Hunter Feb 27 '14 at 19:20
  • I guess I'm wondering if their is any direct terminology for this kind of occurrence as I'm not sure my professor would accept my reasoning for why this turns out be be 1.0 when my only answer is "because rounding". – user3361646 Feb 27 '14 at 19:32
  • 1
    I don't believe IEEE-754 guarantees that code like that will ever succeed. The first time around, it probably won't (at least in the general case - it may with certain specific divisors), on most modern platforms, but I suppose if you let it run long enough, after wrapping around infinity a few times, it might manage to hit exactly the right bit pattern, though... – twalberg Feb 27 '14 at 20:06

1 Answers1

0

There is no general rule that ensures that adding n copies of 1.0/n will result in exactly 1.0. This can be explored by changing n in the following program:

import java.math.BigDecimal;

public class Test {
    public static void main(String[] args) {
        int n = 3;
        double[] counts = new double[n+1];
        for(int i=1; i<counts.length; i++){
            counts[i] = counts[i-1]+1.0/n;
        }
        for(double count : counts){
            System.out.println(new BigDecimal(count));
        }
    }
}

For n=3 it prints:

0
0.333333333333333314829616256247390992939472198486328125
0.66666666666666662965923251249478198587894439697265625
1

The first addition adds to zero. The second addition is a simple doubling, so it is also exact. The third and final addition involves rounding, but rounds to 1.0. The exact result of that addition is:

0.999999999999999944488848768742172978818416595458984375

It is closer to 1.0 than it is to the next value down:

0.99999999999999988897769753748434595763683319091796875

so round-to-nearest rounds to 1.0.

However, changing n to 7 results in:

0
0.142857142857142849212692681248881854116916656494140625
0.28571428571428569842538536249776370823383331298828125
0.428571428571428547638078043746645562350749969482421875
0.5714285714285713968507707249955274164676666259765625
0.7142857142857141905523121749865822494029998779296875
0.8571428571428569842538536249776370823383331298828125
0.9999999999999997779553950749686919152736663818359375

Running the original program modified to add 1.0/7 would have resulted in an infinite loop. count would have increased until it was so big that adding 1.0/7 would round to the old value, and then stuck at that value.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75