For-loop with decimal increment !=.5 yields strange results

294 Views Asked by At

Original idea

I have just found my old Commodore 64 computer, hooked it up, and decided to try to learn Basic again. I have just finished chapter 3, in which a simple FOR-loop is demonstrated:

10 FOR NB = 1 TO 10 STEP 1
20 PRINT NB,
30 NEXT NB

This yields, as expected, the following:

1       2       3       4
5       6       7       8
9       10

Introducing floating point numbers

The above result is the same when step is set to 1.0. Other numbers, except 0.5, however cause problems:

If I change the step increment to anything but .5 (or 1), I get strange floating points, apparently appearing earlier the lower the floating point number is set. For the first test, I changed NB to 1 TO 40.

Test results

  • FOR NB = 1 TO 40 STEP .6: Normal results for 1–31, then 31.6000001. To see if I would get weird results further up, I increased NB to 100, and saw the weird numbers starting again from the 42s: 41.2, 41,8, 42.4, 42.9999999, 43.5999999 etc.
  • FOR NB = 1 TO 40 STEP .4: Normal results for 1–7.4, then 7,8000001, then normal results 8.2–22.6, then 22.9999999, 23.3999999 etc.
  • FOR NB = 1 TO 40 STEP .2: Normal results for 1–6.2, then 6.3999999 in .2 increments up until 8.5999999, then changed from 8.7999998 up until 9.9999998, then normal results from 10.2.
  • FOR NB = 1 TO 40 STEP .1: Normal results for 1–3.6, then 3.6999999 etc.
  • FOR NB = 1 TO 40 STEP .05: Normal results for 1–2.3, then 2.34999999 (note extra digit) up until 2.59999999, then 2.65–2.7, then 2.74999999 etc.

Failure iteration number

The steps fail at the following iterations:

  • 0.6 increment fails at iteration
    • 52 (31.6000001),
    • 51–70 is fine,
    • then 71–87 is 0.0000001 to little (exmpl.: 42.9999999),
    • then 88–103 is further one less (ex.: 53.1999998),
    • then 104 onwards is further reduced (ex.: 62.7999997).
  • 0.4 increment fails at iteration
    • 18,
    • 19–55 is fine,
    • 56–64 is at −.9999999,
    • 65 is fine,
    • 66–84 is at −.9999999,
    • 85–100 is fine,
    • 101–116 is +.0000001,
    • 117 continues at 0.000002, and so on.
  • 0.2 increment fails at iteration
    • 28 at −.9999999,
    • 47–107 is fine,
    • 108–140 fails at +0.0000001,
    • 141 onwards fails at +0.0000002, and so on
    • 0.1 increment fails at iteration
    • 28 at −.9999999,
    • 79–88 is fine,
    • 89–90 fails at +0.00000001 (sic),
    • 91–116 is fine,
    • 117–187 fails at +0.0000001,
    • 188 onwards fails at +0.0000002, and so on.
  • 0.05 increment fails at iteration
    • 28–33 at −.00000001,
    • 34–35 is fine,
    • 36–68 fails at −0.00000001,
    • 69–78 is fine,
    • 79–92 fails at +0.00000001,
    • 93–106 fails at +0.00000002,
    • 107 onwards fails at +0.00000003 and so on.

Notes to the above

For the record, I added a counter to ease reporting; the program therefore looks like this:

05 NC = 1
10 FOR NB = 1 TO 100 STEP 0.05: REM 0.6, 0.4, 0.2, 0.1, 0.05
20 PRINT NC;":";NB,
25 NC = NC + 1
30 NEXT NB

Main question

I suspect the issue is with how decimal is translated to binary, but find it strange that it works perfectly fine with .5 steps. What is causing this error, and how could one either remediate it, or how should one account for it? My Commodore runs Basic v2.

1

There are 1 best solutions below

7
On BEST ANSWER

I would guess that since multiples of .5 can be easily translated to base 2 that's why it doesn't produce any issues. I bet that if you try with .25 increment it will also work fine.