# Cautions With for Loops

### The Program

/*****************************************
Program: beers.c
Author: An unknown UMBC Student
Date: Every Semester
Section: Can never remember
Email: unknown@umbc.edu
How many beers are left after 5 rounds?
*****************************************/
#include
int main()
{
/* Declare variable */
float beers ;
/* You'd think this loop will count down from
** 1.0 to 0.0 by the step -0.2, singing each verse
** as it goes, but does it ? */
for (beers = 1.0; beers != 0.0; beers -= 0.2)
{
printf("%f %s\n%f %s\n",
beers, "bottles of beer on the wall",
beers, "bottles of beer");
printf("Take a fifth down, pass it around\n");
printf("%e bottles of beer on the wall\n\n", beers - 0.2 );
}
return 0;
}
### The Sample Run

1.000000 bottles of beer on the wall
1.000000 bottles of beer
Take a fifth down, pass it around
8.000000e-01 bottles of beer on the wall
0.800000 bottles of beer on the wall
0.800000 bottles of beer
Take a fifth down, pass it around
6.000000e-01 bottles of beer on the wall
0.600000 bottles of beer on the wall
0.600000 bottles of beer
Take a fifth down, pass it around
4.000000e-01 bottles of beer on the wall
0.400000 bottles of beer on the wall
0.400000 bottles of beer
Take a fifth down, pass it around
2.000000e-01 bottles of beer on the wall
0.200000 bottles of beer on the wall
0.200000 bottles of beer
Take a fifth down, pass it around
3.278255e-08 bottles of beer on the wall
0.000000 bottles of beer on the wall
0.000000 bottles of beer
Take a fifth down, pass it around
-2.000000e-01 bottles of beer on the wall
-0.200000 bottles of beer on the wall
-0.200000 bottles of beer
Take a fifth down, pass it around
-4.000000e-01 bottles of beer on the wall
-0.400000 bottles of beer on the wall
-0.400000 bottles of beer
Take a fifth down, pass it around
-6.000000e-01 bottles of beer on the wall
-0.600000 bottles of beer on the wall
-0.600000 bottles of beer
Take a fifth down, pass it around
-8.000000e-01 bottles of beer on the wall
-0.800000 bottles of beer on the wall
-0.800000 bottles of beer
Take a fifth down, pass it around
-1.000000e+00 bottles of beer on the wall
-1.000000 bottles of beer on the wall
-1.000000 bottles of beer
Take a fifth down, pass it around
-1.200000e+00 bottles of beer on the wall
## The Lesson

** Don't test floating point numbers for equality.
**
- The culprit: 1/5 is not a terminating fractional number in
base 2 (similar to 1/3 in base 10).

# Fractions in base 2

In base ten (decimal), we use 0.1 to represent 1/10, 0.01 to represent
1/100, 0.001 to represent 1/1000, and so on. In base two (binary), we
use 0.1 to represent 1/2, 0.01 to represent 1/4, and 0.001 to
represent 1/8, etc.
We can determine the binary representation of a fraction using the
following strategy. Suppose the number is stored in the (float or
double) variable `fraction`. Then we can print out each digit
of the number's binary representation as follows:

while (fraction > 0)
{
fraction = fraction * 2 ;
if (fraction >= 1.0)
{
digit = 1 ;
fraction = fraction - 1.0 ;
}
else
{
digit = 0 ;
}
printf("%d\n", digit) ;
}

Using this strategy, we can figure out that the binary representation
of 5/8 = 0.625 (base 10) is 0.101 (base 2).
The value of the variables `fraction` and `digit`
during each iteration of the loop are (in base 10):

iteration fraction digit
1 0.625
1.25 1
0.25
2 0.25
0.5 0
3 0.5
1.0 1
0.0

We can check our answer by noting that 1/2 + 1/8 = 5/8, which is what
0.101 (base 2) means.
If we try the same for 1/5, we will notice that the loop never ends.
So, 1/5 cannot be represented by a finite number of digits in base 2.
This is analogous to the fact that 1/3 is cannot be represented using
a finite number of digits in base 10.

iteration fraction digit
1 0.2
0.4 0
2 0.4
0.8 0
3 0.8
1.6 1
0.6
4 0.6
1.2 1
0.2
5 0.2
0.4 0
6 0.4
0.8 0
7 0.8
1.6 1
0.6
8 0.6
1.2 1
9 0.2
0.4 0
10 0.4
0.8 0
11 0.8
1.6 1
0.6
12 0.6
1.2 1
...

So, 1/5 is 0.0011001100110011... (base 2) repeating.