Shop OBEX P1 Docs P2 Docs Learn Events
32-bit Multiplication Question - Tracy — Parallax Forums

32-bit Multiplication Question - Tracy

ArchiverArchiver Posts: 46,084
edited 2003-09-14 08:13 in General Discussion
I think your following solution works for me:

X=700
y = X * (X ** 7282) ' 1/9 = 7282/65536
debug dec y,cr ' prints 777

That also can be written this way?:

X = 700
Y = X + (X ** (65535/9))
DEBUG DEC Y,CR

Or if I want a better precision like 100/91 I could have like this?:

X = 700
Y = X + (X ** (100 * (65535/91)))
DEBUG DEC Y,CR

Or if I want much better precision like 1000/912 I could have like this?:

X = 700
Y = X + (X ** (1000 * (65535/915)))
DEBUG DEC Y,CR

I don't need a fraction result because Stamp don't recognize it.
Perhaps for DEBUG function that will useful.

Thanks Tracy for your help.

Cheers

--- In basicstamps@yahoogroups.com, Tracy Allen <tracy@e...> wrote:
> >ValueX = 700
> >ValueY = (ValueX * 1000) / 900
> >
> >In the real world that would give me 777.7.... But in BS2 if I
> >multiply 700 * 1000, that would exceed the 16-bit limit. I don't want
> >to multiply it by 10 or 100. I need more precision. As you can see my
> >final value that I was looking for is still 16-bit even though I can't
> >get fractions in BS2 but I'm still happy with 777.
> >
> >- Johari
>
>
> For that example, where 1000 and 900 are constants, the multiplier
is 10/9, so
> X=700
> y=X * 10/9
> debug dec y,cr
> can be done by the Stamp and prints an answer of 777.
>
> If you need one more digit of precision you can do,
> X=700
> y = (X * 10/9 *10) + (X*10//9 *10 /9)
> debug dec y/10,".",dec1 y,cr
>
> which prints 777.7
>
> Another way to do it is to use the ** operator, which works with a 32
> bit intermediate result.
>
> X=700
> y = X + (X ** 7282) ' 1/9 = 7282/65536
> debug dec y,cr ' prints 777
>
> or for more precision,
> y = X*10 + (X*2**36409) '
> debug dec y/10,".",dec1 y,cr ' prints 777.7
>
> The ** method works even when the constants are not simple like 10/9,
> for example, 1023/917 = 1.1156.
>
> If the other values are also variables, not constants, then you have
> to fall back on true double precision methods.
> more on ** and multiply by constant at
> http://www.emesystems.com/BS2math1.htm
> and more on double precision at
> http://www.emesystems.com/BS2math6.htm
>
>
> -- Tracy

Comments

  • ArchiverArchiver Posts: 46,084
    edited 2003-09-13 18:33
    Hi Johari,

    >I think your following solution works for me:
    >
    >X=700
    > y = X * (X ** 7282) ' 1/9 = 7282/65536
    ^
    NOTE: +, not *

    > debug dec y,cr ' prints 777
    >
    >That also can be written this way?:
    >
    >X = 700
    > Y = X + (X ** (65535/9))
    > DEBUG DEC Y,CR


    Yes, that is okay, because the fractional part is simply 1/9. If it
    were a fraction like 17/155, then the equivalent formula would be
    (65536 * 17 / 155), which the stamp could not compute directly. If
    17/155 is a constant known in advance, it is easy, because on your
    calculator the answer is 7188 (rounded up) and you can plug that in
    as a constant. If the 17/155 is not known in advance, but is a
    variable, there is still an way to calculate the quantity (65536 *
    N/D) at run time.

    ' binary long division
    ' N/D a proper fraction, D<32768, N<32768.
    ' calculates N/D*65536
    for J=15 to 0 ' 16 bits
    N=N//D<<1 ' remainder*2
    F.bit0(J)=N/D ' next bit
    next

    This particular workhorse formula is one that I use time and time
    again in my programming.

    Then,

    ' calculate X * (1+N/D), example (1+17/155)
    X = 7000
    y = X * (X ** F) ' F
    debug dec y,cr ' prints 7767



    >
    >Or if I want a better precision like 100/91 I could have like this?:
    >
    >X = 700
    > Y = X + (X ** (100 * (65535/91)))
    > DEBUG DEC Y,CR

    No, for one thing, the term in parens would come out to 72000, which
    is more than the 2^16 word size. Also, it loses precision in the
    divide by 91, as the fractional part is dropped. Same issues with
    the next suggestion.

    >
    >Or if I want much better precision like 1000/912 I could have like this?:
    >
    >X = 700
    > Y = X + (X ** (1000 * (65535/915)))
    > DEBUG DEC Y,CR
    >
    >I don't need a fraction result because Stamp don't recognize it.
    >Perhaps for DEBUG function that will useful.
    >
    >Thanks Tracy for your help.
    >
    >Cheers
    >
    >--- In basicstamps@yahoogroups.com, Tracy Allen <tracy@e...> wrote:
    >> >ValueX = 700
    >> >ValueY = (ValueX * 1000) / 900
    >> >
    >> >In the real world that would give me 777.7.... But in BS2 if I
    >> >multiply 700 * 1000, that would exceed the 16-bit limit. I don't want
    >> >to multiply it by 10 or 100. I need more precision. As you can see my
    >> >final value that I was looking for is still 16-bit even though I can't
    >> >get fractions in BS2 but I'm still happy with 777.
    >> >
    >
    > > >- Johari
    >>
    >>
    >> For that example, where 1000 and 900 are constants, the multiplier
    >is 10/9, so
    >> X=700
    >> y=X * 10/9
    >> debug dec y,cr
    >> can be done by the Stamp and prints an answer of 777.
    >>
    >> If you need one more digit of precision you can do,
    >> X=700
    >> y = (X * 10/9 *10) + (X*10//9 *10 /9)
    >> debug dec y/10,".",dec1 y,cr
    >>
    >> which prints 777.7
    >>
    >> Another way to do it is to use the ** operator, which works with a 32
    >> bit intermediate result.
    >>
    >> X=700
    >> y = X + (X ** 7282) ' 1/9 = 7282/65536
    >> debug dec y,cr ' prints 777
    >>
    >> or for more precision,
    >> y = X*10 + (X*2**36409) '
    >> debug dec y/10,".",dec1 y,cr ' prints 777.7
    >>
    >> The ** method works even when the constants are not simple like 10/9,
    >> for example, 1023/917 = 1.1156.
    >>
    >> If the other values are also variables, not constants, then you have
    >> to fall back on true double precision methods.
    >> more on ** and multiply by constant at
    >> http://www.emesystems.com/BS2math1.htm
    >> and more on double precision at
    >> http://www.emesystems.com/BS2math6.htm
    >>
    >>
    >> -- Tracy
    >
    >
    >To UNSUBSCRIBE, just send mail to:
    > basicstamps-unsubscribe@yahoogroups.com
    >from the same email address that you subscribed. Text in the
    >Subject and Body of the message will be ignored.
    >
    >
    >Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
  • ArchiverArchiver Posts: 46,084
    edited 2003-09-14 08:13
    Hi Tracy,

    Actually what I was looking for is just a fractional
    multiplier/divider from 1.1 to 1.9. That gives me much room compared
    to 1 to 2 which PBasic allow. My InputNum range from 100 to 3500. The
    following code does work for me. With D in the range of 501 to 990, it
    won't go beyond the 16 bit limit. The bonus is I can get multiplier of
    1.01 to 1.09 when D is within 900 to 990. The highest InputNum I can
    have is 65000. Here is the code again:

    Y VAR Word
    X VAR Word 'InputNum
    D VAR Word

    P CON 1000
    MaxWord CON 65535

    start:
    DEBUG "Input Number: "
    DEBUGIN DEC X
    DEBUG CR
    DEBUG "Divider: "
    DEBUGIN DEC D
    Y = X + (X ** (P * (MaxWord/D)))
    DEBUG "Result: ", DEC Y,CR

    BTW 65536 exceeds the Word capacity. In PBasic 2.5 that's illegal. I
    don't know about the earlier versions.

    Cheers,

    - Johari



    --- In basicstamps@yahoogroups.com, Tracy Allen <tracy@e...> wrote:
    > Hi Johari,
    >
    > >I think your following solution works for me:
    > >
    > >X=700
    > > y = X * (X ** 7282) ' 1/9 = 7282/65536
    > ^
    > NOTE: +, not *
    >
    > > debug dec y,cr ' prints 777
    > >
    > >That also can be written this way?:
    > >
    > >X = 700
    > > Y = X + (X ** (65535/9))
    > > DEBUG DEC Y,CR
    >
    >
    > Yes, that is okay, because the fractional part is simply 1/9. If it
    > were a fraction like 17/155, then the equivalent formula would be
    > (65536 * 17 / 155), which the stamp could not compute directly. If
    > 17/155 is a constant known in advance, it is easy, because on your
    > calculator the answer is 7188 (rounded up) and you can plug that in
    > as a constant. If the 17/155 is not known in advance, but is a
    > variable, there is still an way to calculate the quantity (65536 *
    > N/D) at run time.
    >
    > ' binary long division
    > ' N/D a proper fraction, D<32768, N<32768.
    > ' calculates N/D*65536
    > for J=15 to 0 ' 16 bits
    > N=N//D<<1 ' remainder*2
    > F.bit0(J)=N/D ' next bit
    > next
    >
    > This particular workhorse formula is one that I use time and time
    > again in my programming.
    >
    > Then,
    >
    > ' calculate X * (1+N/D), example (1+17/155)
    > X = 7000
    > y = X * (X ** F) ' F
    > debug dec y,cr ' prints 7767
    >
    >
    >
    > >
    > >Or if I want a better precision like 100/91 I could have like this?:
    > >
    > >X = 700
    > > Y = X + (X ** (100 * (65535/91)))
    > > DEBUG DEC Y,CR
    >
    > No, for one thing, the term in parens would come out to 72000, which
    > is more than the 2^16 word size. Also, it loses precision in the
    > divide by 91, as the fractional part is dropped. Same issues with
    > the next suggestion.
    >
    > >
    > >Or if I want much better precision like 1000/912 I could have like
    this?:
    > >
    > >X = 700
    > > Y = X + (X ** (1000 * (65535/915)))
    > > DEBUG DEC Y,CR
    > >
    > >I don't need a fraction result because Stamp don't recognize it.
    > >Perhaps for DEBUG function that will useful.
    > >
    > >Thanks Tracy for your help.
    > >
    > >Cheers
    > >
    > >--- In basicstamps@yahoogroups.com, Tracy Allen <tracy@e...> wrote:
    > >> >ValueX = 700
    > >> >ValueY = (ValueX * 1000) / 900
    > >> >
    > >> >In the real world that would give me 777.7.... But in BS2 if I
    > >> >multiply 700 * 1000, that would exceed the 16-bit limit. I don't
    want
    > >> >to multiply it by 10 or 100. I need more precision. As you can
    see my
    > >> >final value that I was looking for is still 16-bit even though I
    can't
    > >> >get fractions in BS2 but I'm still happy with 777.
    > >> >
    > >
    > > > >- Johari
    > >>
    > >>
    > >> For that example, where 1000 and 900 are constants, the multiplier
    > >is 10/9, so
    > >> X=700
    > >> y=X * 10/9
    > >> debug dec y,cr
    > >> can be done by the Stamp and prints an answer of 777.
    > >>
    > >> If you need one more digit of precision you can do,
    > >> X=700
    > >> y = (X * 10/9 *10) + (X*10//9 *10 /9)
    > >> debug dec y/10,".",dec1 y,cr
    > >>
    > >> which prints 777.7
    > >>
    > >> Another way to do it is to use the ** operator, which works with a 32
    > >> bit intermediate result.
    > >>
    > >> X=700
    > >> y = X + (X ** 7282) ' 1/9 = 7282/65536
    > >> debug dec y,cr ' prints 777
    > >>
    > >> or for more precision,
    > >> y = X*10 + (X*2**36409) '
    > >> debug dec y/10,".",dec1 y,cr ' prints 777.7
    > >>
    > >> The ** method works even when the constants are not simple like 10/9,
    > >> for example, 1023/917 = 1.1156.
    > >>
    > >> If the other values are also variables, not constants, then you have
    > >> to fall back on true double precision methods.
    > >> more on ** and multiply by constant at
    > >> http://www.emesystems.com/BS2math1.htm
    > >> and more on double precision at
    > >> http://www.emesystems.com/BS2math6.htm
    > >>
    > >>
    > >> -- Tracy
    > >
    > >
    > >To UNSUBSCRIBE, just send mail to:
    > > basicstamps-unsubscribe@yahoogroups.com
    > >from the same email address that you subscribed. Text in the
    > >Subject and Body of the message will be ignored.
    > >
    > >
    > >Your use of Yahoo! Groups is subject to
    http://docs.yahoo.com/info/terms/
Sign In or Register to comment.