Being precise on the C64

A few weeks ago, I wrote about how the C64 handles floating points and the effect of having “just” 5 bytes for these numbers when converting from binary to decimal.
Another one of those limitations is the way the breadbox works with integers.

Integer numbers are stored without problem on the C64 as long as they have no more than 9 significant digits. So integers less than 999.999.999 are no problem, but what happens when you start doing multiplications etc. and the result will have more (or rather needs) more digits? Take for instance 999.999.999 to the power 3? What would be the result on your Commodore? Well, let’s give it a try.

1E+27, that’s a 1 with 27 zeros. Now, that’s not 100% correct, as the C64 has done some rounding. The correct value is 999.999.997.000.000.002.999.999.999, so that’s a mistake of 2.999.999.997.000.000.001… hmmm not so good when we need to do precise calculations!

So, are we to discard the C64 for these type of calculations? No, luckily we can do some tricks with arrays and here’s how.
Say we want to store the number 987.654. Instead of storing it in one single variable, we’ll use an array to store the digits in groups of 4.
So we’ll have M(1) = 98 and M(0) = 7654. The original number is then recovered as M = M(1)*10^4 + M(0)
Now, let’s say we want to multiply M (=987.654) with N (=23.456). Calculating this on our C64 would again introduce rounding errors as seen above.
The value we got was 23.166.412.200 whereas it should actually be 23.166.412.224, so a difference of 24.

By applying our array-trick however with the grouping per 4 digits, we can get it absolutely correct:
M(1) = 98, M(0) = 7654
N(1) = 2, N(1) = 3456

Now we perform the following calculations:
C(0) = M(0)*N(0)
C(1) = M(1)*N(0) + M(0)*N(1)
C(2) = M(1)*N(1)

This returns:
C(0) = 26452224
C(1) = 353996
C(2) = 196

Again we group the results per 4 digits, by stripping of the digits from the left until 4 are left and adding them to the next array. This would then give us:
C(0) = 2224
C(1) = 353996 + 2645 = 356641

We continue the process now for the next array:
C(1) = 6641
C(2) = 196 + 35 = 231

So, we have C(2) = 231, C(1) = 6641, C(0) = 2224

Now write the arrays one after the other and we get 231 6641 2224, the correct result!

This process is generic, we can put it in a small basic routine that will calculate the powers of a number between 2 and 999.999.999 accurately up to 40 digits. You can go even higher on your C64 as this program demonstrates (you can get it here), by simply changing the value of X in line 80. The value of X+1 times 4 is the degree of precision.

Below you can see the calculation of 999.999.999 to the power 2, 3 and 4 with perfect precision. The first screenshot is with a precision of 40 digits, the second with 60 digits!

So there you have it, extreme precision on your Commodore C64!

Share This Post

DeliciousDiggGoogleStumbleuponRedditTechnoratiYahooBloggerMyspaceRSS

Leave a Reply

Your email address will not be published. Required fields are marked *