Searching \ for 'fast % routine' in subject line. ()
Help us get a faster server
FAQ page: www.piclist.com/techref/index.htm?key=fast+routine
Search entire site for: 'fast routine'.

Truncated match.
'fast % routine'
2000\02\24@205608 by

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
movwf tempL
clrf PCntL
bcf status,carry
rrf PCntH
rrf PCntL
rrf PCntH
rrf PCntL
rrf PCntH,w
movwf tempH
rrf PCntL,w
clrf tempH
bcf status,carry
rlf tempL
rlf tempH
rlf tempL
rlf tempH
movf tempL,w
return

btfsc status,carry
incf PCntH
movf tempH,w
return

--
Best regards

Tony

http://www.picnpoke.com
salespicnpoke.com

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

RETURN

?

Scott

Scott Dattalo wrote:

> You mean like this:
[snip]

Gee Scott, what took you so long :-))

--
Best regards

Tony

http://www.picnpoke.com
salespicnpoke.com

On Fri, 25 Feb 2000, Tony Nixon wrote:

> 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.

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

and,

1/255 = 1/(-1+256) = 1/256 * ( 1 + 1/256 + 1/256/256 + ...)

p = p' + p'/256 + p'/256/256 + ...

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).

Scott

2000\02\24@235542 by
Scott Dattalo wrote:

> Well, the first one was a fast mod routine and then it dawned on me you
> meant percentage :).

I actually tested the routine with 256 and it doesn't make a great deal
of difference (if any). I was going to dump it into Excel, but no time
yet.

Thanks anyway, I've already implemented it.

--
Best regards

Tony

http://www.picnpoke.com
salespicnpoke.com

Hi Guys,
Could you explain that one more time for the dummy?

John

{Original Message removed}
Nice done,  Scott!

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
{Quote hidden}

Nikolai

On Friday, February 25, 2000 Scott Dattalo wrote:
{Quote hidden}

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...

Cheers

Mike

> {Original Message removed}
> 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.

percentify
; input in W, output in temp
movwf temp
bcf status,c
rrf temp,f              ;temp = input * 128 / 256
addwf temp,f            ;carry/temp = input * 384 / 256
rrf temp,f              ;temp = input * 192 / 256
bcf status,c
rrf temp,f              ;temp = input * 96 / 256
swapf temp,w
andlw 0x0F              ;w = input * 6 / 256
addwf temp,f            ;temp = input * 102 / 256
;or:    addwf temp,w     for result in w
return

Jason Harper

Hi Scott.

Nice code ;-)

{Quote hidden}

Possible realization of 1 + 1/256 + ... correction.

;1/256 * (1 + 1/256) =~ 0.999985 / 255 ;

scale255to100:                  ;25 = 16+8+1
clrf    temp            ;int
clrf    temp1           ;frac

rrf     temp,F          ;/2
rrf     temp1,F

rrf     temp,F          ;/4
rrf     temp1,F
rrf     temp,F          ;/8
rrf     temp1,F

rrf     temp,F          ;/16
rrf     temp1,F

rrf     temp,F          ;/32
rrf     temp1,F

rrf     temp,W          ;/64
rrf     temp1,F
;
;       movwf   temp2           ;1/256/256     if longer tail
;       movwf   temp3           ;1/256/256/256 is required
;       etc...
;
addwf   temp1,F         ;1 + 1/256 correction
btfss   temp1,7         ;either round if >= 0.5
skpnc                   ;or take carry
addlw   1               ;temp1 holds frac part
;
;       movwf   temp            ;answer is either W or temp
return

If >=0.5 correction isn't required <btfss temp1,7> line
should be commented.

WBR Dmitry.

More... (looser matching)
- Last day of these posts
- In 2000 , 2001 only
- Today
- New search...