Basic Stamp Math Puzzle
Basic Stamp Math Gurus,
I need your help. I am trying to calculate a ratio of 16-bit numbers
to be used with the '*/' function. I will attempt to explain my
problem with an example:
A=1300
B=500
A/B=2 remainder 300
What is the best way to reduce my ratio so that my remainder is less
than 256?
The answer should be $0299.
TIA,
Roger Byrum
I need your help. I am trying to calculate a ratio of 16-bit numbers
to be used with the '*/' function. I will attempt to explain my
problem with an example:
A=1300
B=500
A/B=2 remainder 300
What is the best way to reduce my ratio so that my remainder is less
than 256?
The answer should be $0299.
TIA,
Roger Byrum
Comments
> 16-bit numbers to be used with the '*/' function.
> I will attempt to explain my problem with an example:
> A=1300
> B=500
> A/B=2 remainder 300
> What is the best way to reduce my ratio so that my
> remainder is less than 256? The answer should be $0299.
> TIA,
> Roger Byrum
Hi Roger,
It would help to know what you are going to do with the */ operator. What
do you mean by, "The answer should be $0299"? I have a write-up on how to
use */ and ** at:
http://www.emesystems.com/BS2math1.htm
- Tracy
> > I need your help. I am trying to calculate a ratio of
> > 16-bit numbers to be used with the '*/' function.
> > I will attempt to explain my problem with an example:
> > A=1300
> > B=500
> > A/B=2 remainder 300
> > What is the best way to reduce my ratio so that my
> > remainder is less than 256? The answer should be $0299.
> > TIA,
> > Roger Byrum
>
> Hi Roger,
> It would help to know what you are going to do with the */
operator. What
> do you mean by, "The answer should be $0299"? I have a write-up on
how to
> use */ and ** at:
> http://www.emesystems.com/BS2math1.htm
>
> - Tracy
Thank you for the response Tracy.
I intend to use the */ function to simulate a floating point number.
An example in the book shows how to use it to calculate PI 3.14=$0324.
The high byte, $03, is the whole number part, and the low byte, $24,
is the fractional part. The fractional part is multiplied by 256 to
arrive at a value for the low byte. It can be though of as a
fraction with $100 as the denominator: i.e. $24/$100 = ~0.14.
To clarify my problem, I have two 16 bit variables that constitute my
ratio. From the example above, the numerator is N=1300 and the
denominator is D=500. It is my intension to multiply this ratio
against another 16 bit variable. One solution would be to first
multiply by the numerator and then divide by the denominator. By
doing so, I run the risk of overflowing the 16 bit limit on the
multiplication or at the other extreme, if I use **, the values may
be too small and I get zero.
This line of though brought me to the */ function. I loose a little
accuracy but that won't kill me in my application.
1300/500 = 2.6 -> $02 (whole number) .6*256=153.6 -> $99 (fraction)
$0299=665 -> 665/256=2.598 or ~2.6
I should note that in my application, my 16 bit ratio will routinely
be greater than and less than 1.
Sorry if I was so long winded!
Thanks again,
Roger
> An example in the book shows how to use it to calculate PI 3.14=$0324.
> The high byte, $03, is the whole number part, and the low byte, $24,
> is the fractional part. The fractional part is multiplied by 256 to
> arrive at a value for the low byte. It can be though of as a
> fraction with $100 as the denominator: i.e. $24/$100 = ~0.14.
Hmm.... that example sounds familiar.
>
> To clarify my problem, I have two 16 bit variables that constitute my
> ratio. From the example above, the numerator is N=1300 and the
> denominator is D=500. It is my intension to multiply this ratio
> against another 16 bit variable. One solution would be to first
> multiply by the numerator and then divide by the denominator. By
> doing so, I run the risk of overflowing the 16 bit limit on the
> multiplication or at the other extreme, if I use **, the values may
> be too small and I get zero.
>
> This line of though brought me to the */ function. I loose a little
> accuracy but that won't kill me in my application.
>
> 1300/500 = 2.6 -> $02 (whole number) .6*256=153.6 -> $99 (fraction)
>
> $0299=665 -> 665/256=2.598 or ~2.6
>
w=N/D ' 2
w=w*$100 ' get ready
wf=N//D ' 300 (remainder)
wf=wf*$100/D ' wf = 153 (truncated 153.6)
w.lowbyte=wf.lowbyte ' w = $0299
Y=X*/w
Is that what you are asking? By the way -- just to mention it -- another
answer would be
to use a PAK-I connected to the Stamp with 2 pins -- then you could use real
floating point:
fpx=D ' get D (500) into PAK's X reg
gosub floadint
gosub fswap ' Swap X and Y registers
fpx=N ' Now load N as an integer
gosub floadint
gosub fdiv ' Divide
gosub fswap ' Put result in Y
fpx=X ' Load X (number to be multiplied by N/D)
gosub floadint
gosub fmult ' Multiply
gosub fint ' read integer
debug ?fpx ' correct answer
Regards,
Al Williams
AWC
*Floating point math for the Stamp, PIC, SX, or any microcontroller at
http://www.al-williams.com/awce/pak1.htm
> > I intend to use the */ function to simulate a floating point
number.
> > An example in the book shows how to use it to calculate PI
3.14=$0324.
> > The high byte, $03, is the whole number part, and the low byte,
$24,
> > is the fractional part. The fractional part is multiplied by 256
to
> > arrive at a value for the low byte. It can be though of as a
> > fraction with $100 as the denominator: i.e. $24/$100 = ~0.14.
>
> Hmm.... that example sounds familiar.
>
> >
> > To clarify my problem, I have two 16 bit variables that
constitute my
> > ratio. From the example above, the numerator is N=1300 and the
> > denominator is D=500. It is my intension to multiply this ratio
> > against another 16 bit variable. One solution would be to first
> > multiply by the numerator and then divide by the denominator. By
> > doing so, I run the risk of overflowing the 16 bit limit on the
> > multiplication or at the other extreme, if I use **, the values
may
> > be too small and I get zero.
> >
> > This line of though brought me to the */ function. I loose a
little
> > accuracy but that won't kill me in my application.
> >
> > 1300/500 = 2.6 -> $02 (whole number) .6*256=153.6 -> $99
(fraction)
> >
> > $0299=665 -> 665/256=2.598 or ~2.6
> >
>
> w=N/D ' 2
> w=w*$100 ' get ready
> wf=N//D ' 300 (remainder)
> wf=wf*$100/D ' wf = 153 (truncated 153.6)
> w.lowbyte=wf.lowbyte ' w = $0299
>
> Y=X*/w
>
> Is that what you are asking? By the way -- just to mention it --
another
> answer would be
> to use a PAK-I connected to the Stamp with 2 pins -- then you could
use real
> floating point:
>
> fpx=D ' get D (500) into PAK's X reg
> gosub floadint
> gosub fswap ' Swap X and Y registers
> fpx=N ' Now load N as an integer
> gosub floadint
> gosub fdiv ' Divide
> gosub fswap ' Put result in Y
> fpx=X ' Load X (number to be multiplied by N/D)
> gosub floadint
> gosub fmult ' Multiply
> gosub fint ' read integer
> debug ?fpx ' correct answer
>
> Regards,
>
> Al Williams
> AWC
> *Floating point math for the Stamp, PIC, SX, or any microcontroller
at
> http://www.al-williams.com/awce/pak1.htm
Big Thanks Al! This is exactly what I need.
Roger Byrum
Logansport, IN
> > w=w*$100 ' get ready
> > wf=N//D ' 300 (remainder)
> > wf=wf*$100/D ' wf = 153 (truncated 153.6)
> > w.lowbyte=wf.lowbyte ' w = $0299
> >
> > Y=X*/w
> >
Actually, I wrote this early. The second line would probably be better
written:
w=w<<8
or even better:
w.highbyte=w.lowbyte
Any of the 3 lines ought to work, but the last one is probably (probably)
faster.
Come to think of it, I guess
wf=wf*$100/D would be smarter to write as:
wf=wf<<8/D
Can't use the hibyte/lowbyte trick for reasons I will leave as an exercise.
Regards,
Al Williams
AWC
* Tax special from now to April 17th. Order a copy of Microcontroller
Projects with Basic Stamps and get an ASP-II free.
http://www.al-williams.com/awce/sbook.htm
Operators */ and ** are easily applicable to constant fractions (like pi)
that you can calculate in advance.
However, it sounds like that is not what you want to do. You are looking
for a solution to
Y=X*A/B
where all three quantities on the right are variables. Is that right?
That is a different story.
There as Al pointed out, you may be able to do a division in steps. Here
is the formula compressed into one line:
Y = A/B * 256 + (A//B * 256 /
BTW, the */ operator is commutative: X*/Y = Y*/X. The caveat on the above
formula is that the value of (A//B*256) has to be less than 65536, which
means A//B has to be less than 256, which is always satisfied when B is
less than 256. Also, note that A/B has to be less than 256. Those are
pretty strong constraints.
For example, you suggested the fraction A/B=1300/500, and the remainder
happens to be R=300, so the formula will blow up. (That is true of Al's
formula too--sorry Al!--it will blow up in the step wf=wf*$100/D, because
wf=300. The formula as written will return 22, not the correct value, 153.
Same thing if you write it as wf=wf<<8/D). In order not to blow up, the
denominator has to satisfy the inequality: 1300-N*X<256, where N and X are
integers. If N=2, then 650>X>522. Those are the values of X for which
the remainder is less than 256. But as you see, it is an extremely ad hoc
result. It only works if you know pretty well in advance what the range of
the variables is going to be. Integer inequalities are a bear. Maybe that
was the substance of your original question?
A more robust approach involves a binary long division. I have some
examples posted at:
http://www.emesystems.com/BS2math2.htm
That is for equations where there is a variable in the denominator. The
Y=X*A/B problem can be solved with a binary long division followed by a **
operator. But you still have to think about the constraints! But the main
constraint is only that 0<B<32768.
Also at
http://www.emesystems.com/BS2math1.htm
there are more examples using */ and ** for dealing with the case when A/B
is a constant fraction known in advance.
I hope that helps.
-- Tracy Allen
Electronically Monitored Ecosystems
http://www.emesystems.com
> formula too--sorry Al!--it will blow up in the step wf=wf*$100/D, because
> wf=300. The formula as written will return 22, not the correct
> value, 153.
I should know better than to answer anything before 9AM. Of course, you are
correct, with the numbers supplied, an overflow occurs. Sorry!
Regards,
Al Williams
AWC
* Tax special from now to April 17th. Order a copy of Microcontroller
Projects with Basic Stamps and get an ASP-II free.
http://www.al-williams.com/awce/sbook.htm