> Hi all,
>
> I need a fast 0 - 255 -> % routine
>
> Eg Byte value = 89
> % value = 34
>
> 89 / 255 * 100
>
> I did this routine - any others??
>
> Value in W on entry
> Result in PcntH on return
>
> ToPcnt movwf PCntH
<big snip>
You mean like this:
;*******************************************************************
;scale_hex2dec
; The purpose of this routine is to scale a hexadecimal byte to a
;decimal byte. In other words, if 'h' is a hexadecimal byte then
;the scaled decimal equivalent 'd' is:
; d = h * 100/256.
;Note that this can be simplified:
; d = h * 25 / 64 = h * 0x19 / 0x40
;Multiplication and division can be expressed in terms of shift lefts
;and shift rights:
; d = [ (h<<4) + (h<<3) + h ] >> 6
;The program divides the shifting as follows so that carries are
automatically
;taken care of:
; d = (h + (h + (h>>3)) >> 1) >> 2
;
;Inputs: W - should contain 'h', the hexadecimal value to be scaled
;Outputs: W - The scaled hexadecimal value is returned in W
;Memory: temp
;Calls: none
scale_hex2dec
MOVWF temp ;Hex value is in W.
CLRC ;Clear the Carry bit so it doesn't affect RRF
RRF temp,F
CLRC
RRF temp,F
CLRC
RRF temp,F ;temp = h>>3
ADDWF temp,F ;temp = h + (h>>3)
RRF temp,F ;temp = (h + (h>>3)) >> 1
ADDWF temp,F ;temp = h + ((h + (h>>3)) >> 1)
RRF temp,F
CLRC
RRF temp,W ;d = W = (h + (h + (h>>3)) >> 1) >> 2
> Scott Dattalo wrote:
>
> > You mean like this:
> [snip]
>
>
> Gee Scott, what took you so long :-))
Well, the first one was a fast mod routine and then it dawned on me you
meant percentage :).
If you look closely, it doesn't do exactly what you asked. The one I
posted divides (implicitly) by 256 while you were asking for 255. The
error is quite small, but if necessary can be removed.
You're asking for
p = x * 100/255
and I gave you a solution for
p' = x * 100/256
but you can do a little arithmetic:
p = x * 100/256 * (256/255)
= p' * (256/255)
= p' * (1 + 1/255)
= p' + p'/255
Now since p' is going to be less than 100, then the first correction is
going to be less than 1/2 and there will be no rounding. Hence the answer
IS the same. However, if you wanted a fractional result, well here you go.
Looks like you get a repeating fraction much like you get when you divide
by 9 (10 - 1 instead of 256 - 1).
To add, if Tony needs a little better precision (especially for higher
values of input byte), one more term should be added, so that
d = (((h >> 3 + h) >> 3 + h) >> 1 + h) >> 2 = h * (1/4 + 1/8 + 1/64 +
1/512)
This adds only 6 cycles, and reduces errors from 51 to 11 cases per
all combinations of input (in both routines absolute errors are small,
+-1).
> MOVWF temp ;Hex value is in W.
> CLRC ;Clear the Carry bit so it doesn't affect RRF
RRF temp,F
CLRC
RRF temp,F
CLRC
RRF temp,F
ADDWF temp, F {Quote hidden}
On Friday, February 25, 2000 Scott Dattalo wrote: {Quote hidden}
> On Fri, 25 Feb 2000, Tony Nixon wrote:
>> Hi all,
>>
>> I need a fast 0 - 255 -> % routine
>>
>> Eg Byte value = 89
>> % value = 34
>>
>> 89 / 255 * 100
>>
>> I did this routine - any others??
>>
>> Value in W on entry
>> Result in PcntH on return
>>
>> ToPcnt movwf PCntH
> <big snip>
> You mean like this:
> ;*******************************************************************
> ;scale_hex2dec
> ; The purpose of this routine is to scale a hexadecimal byte to a
> ;decimal byte. In other words, if 'h' is a hexadecimal byte then
> ;the scaled decimal equivalent 'd' is:
> ; d = h * 100/256.
> ;Note that this can be simplified:
> ; d = h * 25 / 64 = h * 0x19 / 0x40
> ;Multiplication and division can be expressed in terms of shift lefts
> ;and shift rights:
> ; d = [ (h<<4) + (h<<3) + h ] >> 6
> ;The program divides the shifting as follows so that carries are
> automatically
> ;taken care of:
> ; d = (h + (h + (h>>3)) >> 1) >> 2
> ;
> ;Inputs: W - should contain 'h', the hexadecimal value to be scaled
> ;Outputs: W - The scaled hexadecimal value is returned in W
> ;Memory: temp
> ;Calls: none
> scale_hex2dec
> MOVWF temp ;Hex value is in W.
> CLRC ;Clear the Carry bit so it doesn't affect RRF
> RRF temp,F
> CLRC
> RRF temp,F
> CLRC
> RRF temp,F ;temp = h>>3
> ADDWF temp,F ;temp = h + (h>>3)
> RRF temp,F ;temp = (h + (h>>3)) >> 1
> ADDWF temp,F ;temp = h + ((h + (h>>3)) >> 1)
> RRF temp,F
> CLRC
> RRF temp,W ;d = W = (h + (h + (h>>3)) >> 1) >> 2
This was done last year some time IIRC. I offered a simmlar (although
nowhere near as good as Scotts solution) that also divided by 256 instead of
255. There was a long thread regarding "fixing" this error, I'll have to
trawl through the archives and see what the conclusion was...
> I need a fast 0 - 255 -> % routine
>
> Eg Byte value = 89
> % value = 34
>
> 89 / 255 * 100
The fastest routine, of course, would be a 256 byte lookup table...
Assuming that code space is also a concern, try this: it's a bit shorter
than the other solutions I've seen posted. Note that it actually
calculates input * 102 / 256, but due to roundoff errors it produces 100
for an input of 255, so it should do the job for you.