To highlight what I'm talking about above, let's do some really simple division and convert fractions to decimals:
1 / 1 = 1
1 / 2 = .5
1 / 3 = .3333333
1 / 4 = .25
1 / 5 = .2
1 / 6 = .1666667
1 / 7 = .1428571
1 / 8 = .125
1 / 9 = .1111111
1 / 10 = .1
1 / 11 = 9.090909E-02
1 / 12 = 8.333334E-02
1 / 13 = 7.692308E-02
1 / 14 = 7.142857E-02
1 / 15 = 6.666667E-02
1 / 16 = .0625
1 / 17 = 5.882353E-02
1 / 18 = 5.555556E-02
1 / 19 = 5.263158E-02
1 / 20 = .05
Now, if we look at the factors of the denominators above, we see this:
1 / (1)
1 / (2)
1 / (3)
1 / (2 * 2)
1 / (5)
1 / (2 * 3)
1 / (7)
1 / (2 * 2 * 2)
1 / (3 * 3)
1 / (2 * 5)
Now, since this is base-10 math, the factors of base-10 would be (1 * 2 * 5)....
As long as our denominator ONLY has those factors (1, 2, or 5) in it, we can have PERFECT DECIMAL REPRESENTATION for our fraction. 1 / 20 *is* 0.05 -- perfectly! No imperfections. No rounding. No "close enough", or repeating digits, or irrational never-ending numbers. The demonimators of 20 are (1 * 2 * 2* 5), and those denominators match our base, so we can perfectly represent that value in decimal form.
And with that said, binary values (which is how a computer tends to store things), follows that *EXACT* same rule!
Base-2's factors are .... (1 * 2).
1 * 2... and that's it!!
So the *only* numbers which we can represent perfectly in binary are going have a denominator which factors to a power of 2.
1 / 2 -- yep! WE can represent it perfectly in binary!
1 / 4 -- yep! We can represent it perfectly in binary!
1 / 6 -- nope... 6 is (2 * 3). 3 is NOT a factor of 2. This is going to be an imperfect fraction and WILL leading to floating point errors over time.
1 / 8 -- yep! We can represent it perfectly in binary!
1 / 10 -- nope... 10 is (2 * 5). 5 is NOT a factor of 2. This is going to be an imperfect fraction.
.
.
.
Which means the only real frsctions we can represent perfectly and not have any sort of math issues with, in binary are all powers of 2.
Halves. (1/2)
Fourths. (1/4, 2/4, 3/4)
Eighths. (1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8)
Sixteenths.
Thirthy-seconds.
Anything else is going to *always* be an imperfect representation and will, over time, add up to give floating point errors.
(Which is why if precision is important to your program, you might consider counting by 1/8 or 1/16, rather than by 1/10.)
And for those of the "Show Me" variety of people, let's take a look at how 1 / 6 performs... I predicted above that it'd glitch over time as it's an "imperfect representation" in base-2. Try this and see for yourself:
1 / 1 = 1
1 / 2 = .5
1 / 3 = .3333333
1 / 4 = .25
1 / 5 = .2
1 / 6 = .1666667
1 / 7 = .1428571
1 / 8 = .125
1 / 9 = .1111111
1 / 10 = .1
1 / 11 = 9.090909E-02
1 / 12 = 8.333334E-02
1 / 13 = 7.692308E-02
1 / 14 = 7.142857E-02
1 / 15 = 6.666667E-02
1 / 16 = .0625
1 / 17 = 5.882353E-02
1 / 18 = 5.555556E-02
1 / 19 = 5.263158E-02
1 / 20 = .05
Now, if we look at the factors of the denominators above, we see this:
1 / (1)
1 / (2)
1 / (3)
1 / (2 * 2)
1 / (5)
1 / (2 * 3)
1 / (7)
1 / (2 * 2 * 2)
1 / (3 * 3)
1 / (2 * 5)
Now, since this is base-10 math, the factors of base-10 would be (1 * 2 * 5)....
As long as our denominator ONLY has those factors (1, 2, or 5) in it, we can have PERFECT DECIMAL REPRESENTATION for our fraction. 1 / 20 *is* 0.05 -- perfectly! No imperfections. No rounding. No "close enough", or repeating digits, or irrational never-ending numbers. The demonimators of 20 are (1 * 2 * 2* 5), and those denominators match our base, so we can perfectly represent that value in decimal form.
And with that said, binary values (which is how a computer tends to store things), follows that *EXACT* same rule!
Base-2's factors are .... (1 * 2).
1 * 2... and that's it!!
So the *only* numbers which we can represent perfectly in binary are going have a denominator which factors to a power of 2.
1 / 2 -- yep! WE can represent it perfectly in binary!
1 / 4 -- yep! We can represent it perfectly in binary!
1 / 6 -- nope... 6 is (2 * 3). 3 is NOT a factor of 2. This is going to be an imperfect fraction and WILL leading to floating point errors over time.
1 / 8 -- yep! We can represent it perfectly in binary!
1 / 10 -- nope... 10 is (2 * 5). 5 is NOT a factor of 2. This is going to be an imperfect fraction.
.
.
.
Which means the only real frsctions we can represent perfectly and not have any sort of math issues with, in binary are all powers of 2.
Halves. (1/2)
Fourths. (1/4, 2/4, 3/4)
Eighths. (1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8)
Sixteenths.
Thirthy-seconds.
Anything else is going to *always* be an imperfect representation and will, over time, add up to give floating point errors.
(Which is why if precision is important to your program, you might consider counting by 1/8 or 1/16, rather than by 1/10.)
And for those of the "Show Me" variety of people, let's take a look at how 1 / 6 performs... I predicted above that it'd glitch over time as it's an "imperfect representation" in base-2. Try this and see for yourself:
Code: (Select All)
i = 1 / 6
For y = 0 To 9
For x = 1 To 60
a = a + i
Print 60 * y + x, a
Next
Print "See any problem with the math yet?"
Sleep
Next