Is there a way to rearrange the arithmetic to achieve resolution in steps of 1?

- Thread starter cpedw
- Start date

Is there a way to rearrange the arithmetic to achieve resolution in steps of 1?

Personally, I always just drop in a version of a code snippet subroutine that I devised when first using PICaxe. There might be other snippets or methods, for example I saw that hippy recently did one for binary division from first principles.

Alternatively, a "trick" that I've used (with CALIBADC values) to give double the resolution, is to split the numerator into two halves, add half of the divisor to one of them, divide both and then add the results. That might be extended by dividing into 3 (or 4), but I'd just stick to what I know works.

Cheers, Alan.

Hi cpedw,

just scale like ur'v done or using a high word

just scale like ur'v done or using a high word

Rich (BB code):

```
w1 = 2000 'test 163200 / 640 to 2000
SerTxd(cr,lf,#w1," ")
w1=w1 /4 : w1= 40800 / w1
SerTxd(#w1)
```

Rich (BB code):

```
w1 = 640 'test 163200 / 640 to 2000
SerTxd(cr,lf,#w1," ")
w1=w1 **26317 : w1= $FFFF / w1
SerTxd(#w1)
```

Last edited:

Hi,

Adding 370 bytes of subroutines before you start does seem rather like overkill ! The ** 26317 optimally scales the 163200 to fit in a 16-bit word (65535), but the calculation is still only to 16-bit accuracy so there are some errors (for example note the run of 234 in the range 690 - 700). Splitting the calculation into 3 seems to work well, but uses as many bytes as the 31-bit division routine! The binary division is very slow but, as the result is only 8 bits, the speed can be doubled, by reducing to only 8 iterations.

All these methods give a truncated (smaller) result (except for the direct /4 because its divisor may get truncated), but a "rounded" (up) result (i.e. when the remainder > half the divisor) can be obtained by adding half the divisor to the numerator. That's easy with the binary division method (then just ignore the remainder) but rather "messy" with all the other methods which prescale the numerator.

Here's my /3 method and sample results for all the methods:

Cheers, Alan

Adding 370 bytes of subroutines before you start does seem rather like overkill ! The ** 26317 optimally scales the 163200 to fit in a 16-bit word (65535), but the calculation is still only to 16-bit accuracy so there are some errors (for example note the run of 234 in the range 690 - 700). Splitting the calculation into 3 seems to work well, but uses as many bytes as the 31-bit division routine! The binary division is very slow but, as the result is only 8 bits, the speed can be doubled, by reducing to only 8 iterations.

All these methods give a truncated (smaller) result (except for the direct /4 because its divisor may get truncated), but a "rounded" (up) result (i.e. when the remainder > half the divisor) can be obtained by adding half the divisor to the numerator. That's easy with the binary division method (then just ignore the remainder) but rather "messy" with all the other methods which prescale the numerator.

Here's my /3 method and sample results for all the methods:

Code:

```
symbol DIV3 = 163200 / 3 ; = 54400
for w0 = 690 to 700
w3 = w0 / 3
w1 = DIV3 + w3 + w3 / w0
w1 = DIV3 + w3 / w0 + w1
w1 = DIV3 / w0 + w1
sertxd(cr,lf,#w0," ",#w1)
next
#rem
div /4 opt16 /3 full binary
690 237 236 236 236:rem 360
691 237 236 236 236:rem 124
692 235 236 235 235:rem 580
693 235 235 235 235:rem 345
694 235 235 235 235:rem 110
695 235 234 234 234:rem 570
696 234 234 234 234:rem 336
697 234 234 234 234:rem 102
698 234 234 233 233:rem 566
699 234 234 233 233:rem 333
700 233 233 233 233:rem 100
```

Last edited:

By including the remainder in the calculation you can calculate the answer with a resolution of 1.

Also, because the numerator 40800 is exactly 1/4 of 163,200 the results after including the remainder are exactly correct.

This code calculates the integer division. i.e. it truncates the result.

Code:

```
FOR w1 = 640 to 2000
w2=40800//w1*4 /w1
w2=40800/w1*4 + w2
SerTxd(#w1, " ", #w2, cr, lf)
next w1
```

Code:

```
FOR w1 = 640 to 2000
w2=w1/2
w2=40800//w1*4 + w2/w1
w2=40800/w1*4 + w2
SerTxd(#w1, " ", #w2, cr, lf)
next w1
```

Multiplying by ten we can also extract two decimals,,for testing if we have time and the patience.

Rich (BB code):

```
for W0= 640 to 700 '163200 / 640 to 2000
SerTxd(cr,lf,#W0," ") '690
w1 = 16320 /w0 *10
w2 = 16320 //w0 *10
w1 = w2 /w0 +w1 : SerTxd(#w1,".")
w1 = w2//w0 *10 /w0 : SerTxd(#w1)
w1 = w2//w0 *10 //w0 *10/w0 : SerTxd(#w1," ") '236.52
w1 = w0 **26316 : w1 = 65531 / w1 '65531 /163200 x65536 +1 = 26316
SerTxd(#w1," ") '236
W2 = w0/2 ' round up
w1 = 16320 //w0 *10 +W2 /w0
w1 = 16320 /w0 *10 +w1
SerTxd(#w1," ") '237
next W0
```