HP 12C Modulus

This program takes the modulus of two numbers:

Y MOD X = X * FRAC(Y/X)

In this program, X > 0 and Y > 0.

Code:

STEP CODE KEY

01 10 ÷

02 43, 36 LST x

03 34 X<>Y

04 43, 24 FRAC

05 20 *

06 43, 33, 00 GTO 00

Input: Y [ENTER] X [R/S], Result: Y MOD X

Test 1: 124 MOD 77 = 47

Test 2: 3862 MOD 108 = 82

(07-15-2016 02:37 AM)Eddie W. Shore Wrote: [ -> ]This program takes the modulus of two numbers:

Y MOD X = X * FRAC(Y/X)

That's not a good idea: roundoff errors will spoil the results.

Consider your two examples:

124 mod 77 does not return 47 but 46,99999997

3862 mod 108 does not return 82 but 82,00000008

That's why you better use the relation y mod x = y – x * INT(y/x) instead.

Code:

`01- 34 x<>y`

02- 44 0 STO 0

03- 34 x<>y

04- 10 ÷

05- 43 36 LSTX

06- 34 x<>y

07- 43 25 INTG

08- 20 x

09- 44 30 0 STO- 0

10- 33 R↓

11- 45 0 RCL 0

12- 44,33 00 GTO 00

That's a bit longer and requires one data register, but it works.

The R↓ in line 11 was included to preserve the initiial values in T and Z.

Dieter

(07-15-2016 06:32 PM)Dieter Wrote: [ -> ] (07-15-2016 02:37 AM)Eddie W. Shore Wrote: [ -> ]This program takes the modulus of two numbers:

Y MOD X = X * FRAC(Y/X)

That's not a good idea: roundoff errors will spoil the results.

Consider your two examples:

124 mod 77 does not return 47 but 46,99999997

3862 mod 108 does not return 82 but 82,00000008

That's why you better use the relation y mod x = y – x * INT(y/x) instead.

Code:

`01- 34 x<>y`

02- 44 0 STO 0

03- 34 x<>y

04- 10 ÷

05- 43 36 LSTX

06- 34 x<>y

07- 43 25 INTG

08- 20 x

09- 44 30 0 STO- 0

10- 33 R↓

11- 45 0 RCL 0

12- 44,33 00 GTO 00

That's a bit longer and requires one data register, but it works.

The R↓ in line 11 was included to preserve the initiial values in T and Z.

Dieter

Here's a routine I wrote about a month ago. One step longer, but it uses only the stack and Last-X register. I wrote it for the HP-38C, but the steps are exactly the same for the HP-12C (but the keycodes would be different). For the two examples given by Dieter, it gets the right results.

Code:

`01- x<>y`

02- Enter

03- Enter

04- R↓

05- R↓

06- R↓

07- ÷

08- LSTX

09- x<>y

10- INTG

11- x

12- -

13- GTO 00

From "

ENTER: Reverse Polish Notation Made Easy", Jean-Daniel Dodin / Keith Jarett, (pg 115):

Code:

`01- 36 ENTER`

02- 36 ENTER

03- 30 -

04- 33 R↓

05- 34 x<>y

06- 43 36 LSTx

07- 10 ÷

08- 43 25 INTG

09- 20 x

10- 30 -

11- 43 33 00 GTO 00

(07-18-2016 10:12 PM)bshoring Wrote: [ -> ]Here's a routine I wrote about a month ago. One step longer, but it uses only the stack and Last-X register.

Great. In the meantime I got exactly the same solution. Many/most other HPs offer a R↑ which can replace the three consecutive R↓, making the program even shorter.

(07-21-2016 11:36 PM)RobertM Wrote: [ -> ]From "ENTER: Reverse Polish Notation Made Easy", Jean-Daniel Dodin / Keith Jarett, (pg 115):

That's a nice one as well. Here's another 10/11 step solution:

Code:

`01 ENTER`

02 ENTER

03 -

04 +

05 /

06 LastX

07 x<>y

08 INT

09 x

10 -

11 GTO 00 or RTN

The first four lines copy the content of Y to Z and T while X and Y are left unchanged.

However, all these solutions destroy the stack, while the version I initially posted keeps the values of Z and T. That's why it requires one data register. I wonder if it is possible to do it only with the stack, i.e. without a data register, while Z and T are still preserved.

Here's another challenge: what about returning y mod x as well as y div x (i.e. the integer quotient of y and x). There are many applications where both values are required at the same time. That's why I once suggested a DIVMOD command for the 34s that returns these two values.

Now, what do you think ?-)

Dieter

(07-25-2016 09:17 AM)I Wrote: [ -> ]Here's another challenge: what about returning y mod x as well as y div x (i.e. the integer quotient of y and x). There are many applications where both values are required at the same time. That's why I once suggested a DIVMOD command for the 34s that returns these two values.

I just realized that the code in the previous post can be extended easily to return both values at the same time – it's just two more steps:

Code:

`01 ENTER`

02 ENTER

03 -

04 +

05 /

06 LastX

07 x<>y

08 INT

09 ENTER

10 R↓

11 x

12 -

13 GTO 00 or RTN

The same can be done with the Dodin/Jarett program by inserting ENTER R↓ between step 08 and 09.

The above version returns the remainder in X and y div x in Y.

3782 [ENTER] 72 [R/S]

=> 38 [X<>Y] 52

There even is a third useful result:

[LastX] => 3744

The largest number ≤ Y that is divisible by X.

Dieter

(07-25-2016 09:46 AM)Dieter Wrote: [ -> ] (07-25-2016 09:17 AM)I Wrote: [ -> ]Here's another challenge: what about returning y mod x as well as y div x (i.e. the integer quotient of y and x). There are many applications where both values are required at the same time. That's why I once suggested a DIVMOD command for the 34s that returns these two values.

I just realized that the code in the previous post can be extended easily to return both values at the same time – it's just two more steps:

Code:

`01 ENTER`

02 ENTER

03 -

04 +

05 /

06 LastX

07 x<>y

08 INT

09 ENTER

10 R↓

11 x

12 -

13 GTO 00 or RTN

The same can be done with the Dodin/Jarett program by inserting ENTER R↓ between step 08 and 09.

The above version returns the remainder in X (and Z) and y div x in Y (and T).

3782 [ENTER] 72 [R/S]

=> 38 [X<>Y] 52

There even is a third useful result:

[LastX] => 3744

The largest number ≤ Y that is divisible by X.

Dieter

Nice program.

When I run 3782 [ENTER] 72 [R/S],

it leaves 38 in X only and 52 in Y, Z, & T.

Works for me.

(07-28-2016 11:01 PM)bshoring Wrote: [ -> ]When I run 3782 [ENTER] 72 [R/S],

it leaves 38 in X only and 52 in Y, Z, & T.

Hmmm... you're right. I am sure I had a version were the two results were in X and Z resp. Y and T.

Anyway – I now corrected my previous post. Thank you for your feedback.

Dieter