Half a number, half it again and add it to the first half.
This is a common riddle, so if you’ve heard it, don’t shout out the answer (people might think your strange for shouting at the internet….)
Take a number. Then, half that number. Then half that half and add it to the first half. Before that gives people a headache, lets do a little example:
Lets use 10 . Then half of ten gives us 5. Then, half five (2.5) and add it to the first half, 5. This gives us 7.5
Continue to half the last half, adding it to the sum of the previous halves. Phew, I hope thats explained properly.i.e. half two point five, and add it the the 7.5 we already have, which give us 8.25
Okay, so the question is this. If we keeping adding on the halves, will we ever reach 10 again? Well, I like Java, so lets get all geeky and model the problem. For this, the double and float data types won’t give us enough decimal places. For this, we’ll need: math.BigDecimal . The Big Decimal. Sounds ominous!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import java.math.BigDecimal; public class Half_of_a_half { public static Integer times_to_loop; /** * @param args the number of times you want to run the loop */ public static void main(String[] args) { calculate(Integer.valueOf(args[0])); } public static void calculate(int times_to_loop) { //The Number we want to half BigDecimal number_to_half = new BigDecimal("10"); //The result of doing the half BigDecimal the_half = new BigDecimal("0"); //The number we want to divide by BigDecimal divider = new BigDecimal("2"); for (int i = 0; i < times_to_loop; i++) { number_to_half = number_to_half.divide(divider); the_half = the_half.add(number_to_half); System.out.println(the_half); } System.out.println("The last number has " + ((Integer) the_half.toString().length() - 2) + " decimal places"); } } |
This code takes a single parameter on the command line: the number of times to half by
e.g.
anton@anton-laptop classes $ java Half_of_a_half 10
5
7.5
8.75
9.375
9.6875
9.84375
9.921875
9.9609375
9.98046875
9.990234375
The last number has 9 decimal places
So as we can see, the decimal places just get long and longer. The additions are never big enough to get us close enough to the original number. Problem solved!
The fun bit is realising the significance of the calculation, or rather, the speed with which it was done. Performing 1000 divisions and additions takes less that 0.2 of a second! Maybe thats not so fast by todays computing ability, but by human standards thats pretty extreme.
anton@anton-laptop classes $ time java Half_of_a_half 1000 > /dev/null
real 0m1.387s
user 0m1.916s
sys 0m0.036s

Of course, you could just do away with the loop and use a formula:
(starting number) – (starting number / (2 ^ (number of iterations))
Since that’s effectively what you’re doing. Adding half of a half to a half is the same as subtracting a quarter – which is a half of a half.
So if we start with 10, iterations 1 to 5 would be represented by:
10 – (10 / 2^1) => 10 – (10 / 2) => 10 – 5 => 5
=> 10 – 1.25 => 8.75
10 – (10 / 2^2) => 10 – (10 / 4) => 10 – 2.5 => 7.5
10 – (10 / 2^3) => 10 – (10 /
10 – (10 / 2^4) => 10 – (10 / 16) => 10 – 0.625 => 9.375
10 – (10 / 2^5) => 10 – (10 / 32) => 10 – 0.3125 => 9.6875
This also definitively answers the question of whether you ever reach ten – you won’t, since you’re always subtracting the result of a division by a power of two (which becomes infinitesimal for large powers, but will never equal zero).
It’s also a good lesson in optimisation. I haven’t tried the Java implementation, but I’ll bet it runs quicker than a loop! Right enough, a significant amount of the time spent in your program is probably all the System.out.println() calls – these actually take up a suprising amount of execution time when you’re doing stuff like this (it is I/O, after all)!
Liam. I’ve got an interesting reply coming up, once I’ve the chance to write it up!!
Anton