Truncated match.
PICList
Thread
'Decimal to Percentage Routine'
1998\12\07@233815
by
Kelly J Kohls

Greetings all !
I am trying to come up with a routine to convert a byte value to a
percentage. That is, for an input value of zero, the output would be
zero. For an input of 255, the output would be 100. The obvious
solution is: Percentage = Trunc(Decimal / 2.55). Since I don't know of
an easy way to divide by a fractional number, I came up with this
alternative:
Percentage = (Decimal * 100) / 255. Now I am faced with having to use
sixteen bit operations for a problem that has eight bit values for both
input and output. If there is an easier way to do this, would someone
please enlighten me? I have been thinking this over for quite some time,
so maybe I "can't see the forest for the trees."
Thanks in advance!
Kelly Kohls
Amateur Radio Callsign: N5TLE
Home EMail Address: spam_OUTkkohlsTakeThisOuTjuno.com or .....n5tleKILLspam@spam@qsl.net
Homepage URL: http://www.qsl.net/n5tle
___________________________________________________________________
You don't need to buy Internet access to use free Internet email.
Get completely free email from Juno at http://www.juno.com/getjuno.html
or call Juno at (800) 654JUNO [6545866]
1998\12\08@012821
by
mwestfal

Kelly J Kohls wrote:
> Percentage = (Decimal * 100) / 255. Now I am faced with having to use
> sixteen bit operations for a problem that has eight bit values for both
> input and output.
If you need speed and are not too worried about using up code space,
you could use a lookup table since you have only(!) 256 possible values.
I *think* this is how it goes:
movlw LOW percent ; get low byte of percent table address
addwf input,F ; and add it to input value to get offset
movlw HIGH percent ; get high byte of percent table adress
skpnc ; would index cross a page boundary?
addlw 0x01 ; yes. Increment page number
movwf PCLATH,F ; load page address for computed goto
movf input,W ; get the offset into the table
call percent ; and look up the corresponding value
movwf output ; .. or whatever you wanna do with it.
....
percent movwf PCL
retlw 0x00 ; 0/255 = 0%
retlw 0x00 ; 1/255 = 0%
retlw 0x01 ; 2/255 = 1%
retlw 0x01 ; 3/255 = 1%
retlw 0x02 ; 4/255 = 2%
.
.
.
retlw 0x64 ; 255/255 = 100%

Mike, N6KUY xyzzyKILLspamacm.org
Linux religious dogma: The Gates of Hell shall not prevail
GCS/M { d+ p+ c++ l u++ e+(*) m++() s/+ !n() h !f g+ w+ t++ r() y+ }

1998\12\08@033413
by
Dr. Imre Bartfai

Hi,
here is a pretty simple solution:
Percentage = (Decimal * 101) >> 8
The operation SHIFT RIGHT 8 should not be commenced. Simply take the MSB
of the result, and it is!
Imre
On Mon, 7 Dec 1998, Kelly J Kohls wrote:
{Quote hidden}> Greetings all !
>
> I am trying to come up with a routine to convert a byte value to a
> percentage. That is, for an input value of zero, the output would be
> zero. For an input of 255, the output would be 100. The obvious
> solution is: Percentage = Trunc(Decimal / 2.55). Since I don't know of
> an easy way to divide by a fractional number, I came up with this
> alternative:
> Percentage = (Decimal * 100) / 255. Now I am faced with having to use
> sixteen bit operations for a problem that has eight bit values for both
> input and output. If there is an easier way to do this, would someone
> please enlighten me? I have been thinking this over for quite some time,
> so maybe I "can't see the forest for the trees."
>
> Thanks in advance!
>
> Kelly Kohls
> Amateur Radio Callsign: N5TLE
> Home EMail Address:
.....kkohlsKILLspam.....juno.com or
EraseMEn5tlespam_OUTTakeThisOuTqsl.net
> Homepage URL:
http://www.qsl.net/n5tle
>
> ___________________________________________________________________
> You don't need to buy Internet access to use free Internet email.
> Get completely free email from Juno at
http://www.juno.com/getjuno.html
> or call Juno at (800) 654JUNO [6545866]
>
>
1998\12\08@065401
by
Caisson

> Van: Kelly J Kohls <kkohlsspam_OUTJUNO.COM>
> Aan: @spam@PICLISTKILLspamMITVMA.MIT.EDU
> Onderwerp: Decimal to Percentage Routine
> Datum: dinsdag 8 december 1998 5:35
>
> Greetings all !
Greetings to you, Kelly.
{Quote hidden}> I am trying to come up with a routine to convert a byte value to a
> percentage. That is, for an input value of zero, the output would be
> zero. For an input of 255, the output would be 100. The obvious
> solution is: Percentage = Trunc(Decimal / 2.55). Since I don't know of
> an easy way to divide by a fractional number, I came up with this
> alternative:
> Percentage = (Decimal * 100) / 255. Now I am faced with having to use
> sixteen bit operations for a problem that has eight bit values for both
> input and output. If there is an easier way to do this, would someone
> please enlighten me? I have been thinking this over for quite some time,
> so maybe I "can't see the forest for the trees."
The 'solution' ? Just don't divide with 'nasty' numbers. Create a number
that is 256 times too big, and than throw way the lowbyte ... In other
words Multiply the number with 100 and that divide by 256 (throw away the
Lowbyte). That should work.
(255 *100)/256 = 99%
Greetz,
Rudy Wieser
1998\12\08@082057
by
wwl
On Mon, 7 Dec 1998 22:20:02 0800, you wrote:
>Kelly J Kohls wrote:
>> Percentage = (Decimal * 100) / 255. Now I am faced with having to use
>> sixteen bit operations for a problem that has eight bit values for both
>> input and output.
>
>If you need speed and are not too worried about using up code space,
>you could use a lookup table since you have only(!) 256 possible values.
And remember that as 1% is more than two counts, you only need to
lookup the top 7 bits, requiring at most 128 entries in the table.
Fewer if accuracy isn't critical  64 entries would still be within
2%.
1998\12\08@115114
by
Scott Dattalo

On Mon, 7 Dec 1998, Kelly J Kohls wrote:
>
> I am trying to come up with a routine to convert a byte value to a
> percentage. That is, for an input value of zero, the output would be
> zero. For an input of 255, the output would be 100. The obvious
> solution is: Percentage = Trunc(Decimal / 2.55). Since I don't know of
> an easy way to divide by a fractional number, I came up with this
> alternative:
> Percentage = (Decimal * 100) / 255. Now I am faced with having to use
> sixteen bit operations for a problem that has eight bit values for both
> input and output. If there is an easier way to do this, would someone
> please enlighten me? I have been thinking this over for quite some time,
> so maybe I "can't see the forest for the trees."
Try this. It's close, but not exactly what you ask (I divide by 256
instead of 255  but there is an approximation available to fix this [I
don't have time to type it in now]):
;*******************************************************************
;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
;the RRF
RRF temp,F
CLRC
RRF temp,F
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
1998\12\08@222416
by
Scott Dattalo

On Tue, 8 Dec 1998, Scott Dattalo wrote:
{Quote hidden}>
>
> On Mon, 7 Dec 1998, Kelly J Kohls wrote:
>
> >
> > I am trying to come up with a routine to convert a byte value to a
> > percentage. That is, for an input value of zero, the output would be
>
> Try this. It's close, but not exactly what you ask (I divide by 256
> instead of 255  but there is an approximation available to fix this [I
> don't have time to type it in now]):
>
> ;*******************************************************************
> ;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
> ;the RRF
> RRF temp,F
> CLRC
> RRF temp,F
>
> 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
You can make this approximation to improve things a little bit. First,
you want to perform this function:
p = d * 100 / 255
and the routine that I provide does this instead:
p = d * 100 / 256
So to modify my routine, you'll need to do something like this:
p' = p * 256 /255 ...............(1)
And you're still stuck with that nasty division. However, there's another
division trick you can try. Consider this power series expansion of
division:
N N / / e \ / e \2 / e \3 \
 =  *  1   +    + ... 
v + e v \ \ v / \ v / \ v / /
In your case, N, the dividend, is a constant (that is, the result
produced from my routine above multiplied by 256). The divisor has
been written as a sum of two variables. Now the object is to find a v that
is easy to divide (for example any power of 2). Since you're dividing by
255, you might as well choose v = 256 and e = 1. The equation then becomes
this:
N N / / 1 \ / 1 \2 / 1 \3 \
 =  *  1 +  +  +  + ... 
v + e 256 \ \256/ \256/ \256/ /
When you substitute equation (1) back in and drop the high order terms you
get this:
/ 1 1 \
p' = p * 256 *   +  
\ 256 256*256 /
/ 1 \
= p *  1 +  
\ 256 /
Two observations:
1) This will not work with my routine because it does not save the
remainders while doing the computation. Thus the division by 256 is like a
shift right 8 positions, and there's nothing but zero to add to this. So
no rounding will occur. (I didn't realize this until type all of this
junk...) A corollary observation is that 256 is close enough to 255 so
that it really doesn't matter (is this true? , if not, perhaps
precompensating p by 1 would be sufficient to make it so.)
2) You can still use this work to form this approximation:
100 * d 25 / / 1 \ / 1 \2 / 1 \3 \
 = d *  *  1 +  +  +  + ... 
255 64 \ \256/ \256/ \256/ /
All of the divisions are simple, so the evaluation should be fast.
1998\12\09@055037
by
Mark Willis
Um, you mean e = 1 there, Scott, I suspect (Just a typo, you know
what you're doing, the equations are all right  just a dropped  sign
that you didn't catch on reviewing, I mention it in case you confused
anyone else <G>)
Mark, KILLspammwillisKILLspamnwlink.com
Scott Dattalo wrote:
{Quote hidden}>
> <snipped>
> N N / / e \ / e \2 / e \3 \
>  =  *  1   +    + ... 
> v + e v \ \ v / \ v / \ v / /
>
> In your case, N, the dividend, is a constant (that is, the result
> produced from my routine above multiplied by 256). The divisor has
> been written as a sum of two variables. Now the object is to find a v that
> is easy to divide (for example any power of 2). Since you're dividing by
> 255, you might as well choose v = 256 and e = 1. The equation then becomes
^^^^ {s/b 1 here}
1998\12\12@210223
by
Kelly J Kohls

Greetings All!
Many thanks to all who responded to my inquiry. After evaluating all of
the options presented and obtaining some information from the Internet on
integer division, I managed to get a routine working that implements the
following equation:
Percent = (Decimal * 20) / 51.
The divide algorithm that I used I obtained from Ian Kaplans website
(http://www.bearcave.com/software/divide.htm). This algorithm implements
a radix2 division operation. If the algorithm ends up being too slow, I
still might use a table. The resulting test program for this algorithm
ended up being about 140 lines long. I considered sending it along with
this post, but thought it was too lengthy. If anybody is interested in
the routine, let me know via a personal email.
Kelly Kohls
Amateur Radio Callsign: N5TLE
Home EMail Address: RemoveMEkkohlsTakeThisOuTjuno.com or spamBeGonen5tlespamBeGoneqsl.net
Homepage URL: http://www.qsl.net/n5tle
___________________________________________________________________
You don't need to buy Internet access to use free Internet email.
Get completely free email from Juno at http://www.juno.com/getjuno.html
or call Juno at (800) 654JUNO [6545866]
More... (looser matching)
 Last day of these posts
 In 1998
, 1999 only
 Today
 New search...