X / Y Working round integer maths to simulate floating point...

HertzHog

Member
A cheeky ask...

I am trying to output the result of X / Y. I suspect it would be easy using a Floating Point Unit or FPU and then picking the digits one by one off the left of an output string discarding initial zeros. That it what I would do in my other programming domains. But, this needs to be battery powered!

I have an ugly algorithm, but I suspect it could be improved in many ways. I could not even say it is bug free. I do not feel it is worth showing!
I am sure others have solved this division, but I could not find it with a quick search. Some signposting is needed. If there is a documented working programme that does this, just a pointer might suffice for me to work it out.

I hope to use an 18m2.
Over time both X and Y will change by incrementing, so I wish to loop and display the current, but changing value of X / Y say every 10 seconds while data slowly accumulates independently in X and Y.
I am not trying to achieve huge precision, as this would be artificial, so 3 significant digits would be fine/ adequate.
I need flexibility, as I do not know whether X or Y will be bigger, as either might be the case i.e. the answer might be more or less than 1.
I need the digits of the answer one at a time from the left in order to display them.
Leading Zeros to be suppressed.
Zeros preferably before a decimal point if less than 1 e.g. 0.654
Both X and Y will be always be independently incrementing positive integers greater than 0 and in word sized variables, but I would like to be able to use the maximum extent of these, to allow X and or Y to grow as big as possible before being 'full'.
Ideally rounding would be conventional rather than just a truncation.
The data in X and Y changes slowly over time so great speed is very unlikely to be required.
I think recursive solutions would not go well with a Picaxe?

Examples of arbitrary snapshots of inputs and outputs...
So for momentary example values of...

X / Y = 1st, 2nd, 3rd digit (one may be with a decimal point)

250 / 5 = 5, 0., 0

255 / 5 = 5, 1., 0

22 / 3 = 7., 3, 3

40 / 100 = 0., 4, 0

64000 / 32000 = 2., 0, 0

I hope that is enough examples to get the idea. I hope I have described the problem, succinctly.

I am struggling to find an efficient, tidy but general solution which is likely to be bug free.

Please don't tackle this unless it appeals to you as I know it is a cheeky ask, but others might be interested in the solution? Can a Picaxe do this? HertzHog.
 

geoff07

Senior Member
It all depends on the range of values in your numbers, and the precision you are after. For example, you might not need more than one decimal point, and your values might all be relatively small. In which case, using word variables and defining values as in tenths or hundredths of a unit might do it. So e.g. 98.7 could be stored as 9870. If your numbers work then you simply divide as normal, but output the value with the decimal point in the appropriate place. You would probably scale up the numerator more than the denominator. Large values would need a different approach.

So 23.7 / 3.2 becomes 2370/32 = 74 or 7.4; 320 / 23.7 becomes 3200 / 237 = 13

If the number of decimals is greater and might vary, you might need to store the significant digits and the number of decimals separately. A little like the exponent form for real numbers in other systems. Then you calculate using the significant digits and then apply the appropriate decimal offset.

To select the digits for output simply divide down, so if the value is e.g. 135 meaning 13.5, then the two parts of the number are

135 / 10 = 13 and 135 // 10 = 5

Sadly, Picaxe does not do local variables so recursion would require complicated work on the stack. Probably not worth the effort.

There is an FPU for Picaxe but I don't think that 'easy' would describe it.
 

AllyCat

Senior Member
Hi,

There are a few threads on the forum concerning such calculations, particularly by Jeremy Leach for example here and here (and several more). But the "double-word" division routine that I posted in the code snippets section should be reasonably easy to use (IMHO) and will run on any M2. There's a slightly updated (and smaller) version in post #10.

As geoff says, PICaxe can handle decimal (fractional) parts by multiplying the raw integers by 10 or 100 etc. and putting the decimal point back into the print formatting, where required. However, in some circumstances, working with "binary fractions" (i.e. by multiplying by 256 or 65536) can be an alternative method, if you can get your head around the concept. In particular, the ** operator has the effect of multiplying by a constant/variable and also dividing by 65,536 at the same time.

Generally, leading zeros can the suppressed (or added) with suitable use of IF statements in the print formatting code.

Cheers, Alan.
 
Top