Searching \ for 'Decimal to Percentage Routine' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/index.htm?key=decimal+percentage
Search entire site for: 'Decimal to Percentage Routine'.

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

picon face
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 E-Mail Address: spam_OUTkkohlsTakeThisOuTspamjuno.com or .....n5tleKILLspamspam@spam@qsl.net
Homepage URL: http://www.qsl.net/n5tle

___________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com/getjuno.html
or call Juno at (800) 654-JUNO [654-5866]

1998\12\08@012821 by mwestfal

flavicon
face
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 xyzzyspamKILLspamacm.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

flavicon
face
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}

1998\12\08@065401 by Caisson

flavicon
face
> Van: Kelly J Kohls <kkohlsspamspam_OUTJUNO.COM>
> Aan: @spam@PICLISTKILLspamspamMITVMA.MIT.EDU
> Onderwerp: Decimal to Percentage Routine
> Datum: dinsdag 8 december 1998 5:35
>
> Greetings all !

Greetings to you, Kelly.

{Quote hidden}

The 'solution' ?  Just don't divide with 'nasty' numbers.  Create a number
that is 256 times too big, and than throw way the low-byte ...  In other
words Multiply the number with 100 and that divide by 256 (throw away the
Low-byte).  That should work.

(255 *100)/256 = 99%

Greetz,
 Rudy Wieser

1998\12\08@082057 by wwl

picon face
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

face
flavicon
face
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

face
flavicon
face
On Tue, 8 Dec 1998, Scott Dattalo wrote:

{Quote hidden}

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

flavicon
face
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, KILLspammwillisKILLspamspamnwlink.com

Scott Dattalo wrote:
{Quote hidden}

                                              ^^^^  {s/b -1 here}

1998\12\12@210223 by Kelly J Kohls

picon face
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 radix-2 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 E-Mail Address: RemoveMEkkohlsTakeThisOuTspamjuno.com or spamBeGonen5tlespamBeGonespamqsl.net
Homepage URL: http://www.qsl.net/n5tle

___________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com/getjuno.html
or call Juno at (800) 654-JUNO [654-5866]

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