Re: Assembly Language - Mathematics WITHOUT maths coprocessor



On Mon, 10 Oct 2005 01:39:52 -0400, ¬a\/b <al@xxx> wrote:

for me round in that stage is an error: there is no round,should be only a print_round at end

No, you round every time you truncate the precision of your numbers. What you don't do is reduce the precision of your numbers until the end of your calculation. However, since we're not free to keep an endless supply of digits in our numbers, we're frequently forced to truncate the precision of our numbers even when we're not at the end of our calculation.


For example, add and subtract don't give us any extra bits of precision, so we don't have to do any rounding when we do an add or subtract, and doing so would definately be a bad idea.

However, with multiply, we get extra precision behind the decimal point. For example, 0.7 times 0.7 gives us 0.49, but we can only have one decimal place, so we're forced to reduce the precision of our answer in order to fit it into the fixed point data type we're using.

Now, for example, if you know that you're following up that multiplication with a division, you would be far better off to not reduce the precision at all, since the first step of doing a division is increasing the precision of the number. So if the next step was to divide by 0.3, then instead of rounding 0.49 to 0.5, then increasing the precision again to 0.50 and dividing by 0.3, you'd be much better off to keep the more precise 0.49 and divide that by 0.3.

Keeping additional precision is exactly what floating point math is all about. The exponent field allows you to say how many bits of the matissa are the integer portion, and how many are the fractional portion, and so you can keep the extra precision and just modify the exponent to reflect that.

However, in fixed point math, we don't have an exponent field in the number. So we have to reduce the precision of 0.49, and the best way to do that is to round it to 0.5 rather than to simply truncate it to 0.4.

It's not the rounding that is bad, it's the loss of precision. It's just that people say "you should round until the end" because people usually round when they reduce precision, and they usually don't reduce precision until the end. Everyone uses calculators, and calculators do the precision reduction for them. When someone puts 2 / 3 into a calculator, and the calculator says the answer is 0.666666667, no one ever says that the calculator rounded the result, but that's what it did, because it had to reduce it's precision to 9 decimal places, and that's how that last 6 became a 7.

The rounding that you don't do until the end is when you're calculating a number to two decimal places, you don't round to two decimal places every step of the way, but instead just once at the end. However, if your calculator only has 9 decimal places, then of course you round to 9 decimal places every step of the way. That's what we're doing with the fixed point math. Numbers in "<< 8" format only have room for 2.4 decimal places, so we have to round every result along the way to the 2.4th decimal place.

With that said, my method for rounding division is clearly wrong:

10.0 / 2.8 -> 00001005 / 0028 -> 0035 = 3.5, actual answer 3.5714

The goal is to round that 3.5714 to 3.6, but since we never calculate the extra trailing digits, the only way to do it is to fix up the numerator before doing the divide so that the result will have an additional 1/2 of it's least signifigant bit added to it, so that when the division is done, we get the correct rounded answer. Adding 1/2 of the least signifigant bit doesn't do that, you have to add 1/2 of the denominator.

So the correct formula is this: (a << 8 + b >> 1) / b

Using that formula, you get these results:

10.0 / 2.8 -> 00001014 / 0028 -> 0036 = 3.6, actual answer 3.5714

I wrote a test program this time, which tested that formula with 100 million division problems, so I'm sure I got it right this time.

Of course, another way to do it is to use "(a << 8) / b", and then increment the result if the remainder is greater than "b >> 1", the result is exactly the same either way, however the "(a << 8 + b >> 1) / b" method avoids the need for a conditional jump.

round results are no good results too

Yes, but rounded results are closer to the correct answer than truncated results. With the "* 10" format numbers, it's the difference between each calculation having an error of +/- 0.05 if you round, or 0.05 +/- 0.05 if you don't round. The average error when rounding is 0.00, whereas the average error when truncating is -0.05.
.




Relevant Pages

  • Re: [PHP] RE: round()
    ... Now I see why BCMath was mentioned. ... It doesn't make any difference if you are rounding. ... not precision. ... round results in neither possible result. ...
    (php.general)
  • Re: Calculating Wishes (was hpcatalog.com)
    ... But compared to modern computers, ... Sun-Earth distance useful even if it's know to a precision clearly ... digits of precision. ... > If a calculator offerred say 19 or more digits of precision, ...
    (comp.sys.hp48)
  • Re: its just simple questions..please answer these.
    ... >operations on a calculator. ... >expressed with the precision of the least precise number. ... Your book should discuss 'significant digits' or 'significant ... It is not correct to 'round' intermediate calculations the way I did ...
    (sci.math)
  • Re: Another weirdest hp50g thing...
    ... a limitation on the number of significant digits that the calculator is ... That's eleven digits of precision. ... if instead I run the emulator full speed, ...
    (comp.sys.hp48)
  • Re: rounding to an integer
    ... Dim ii As Integer ... It will all depend on what precision you need for your problem. ... for whole number rounding. ... decimal point as places you want to round to. ...
    (comp.lang.basic.visual.misc)