(12C) Modulus
07-15-2016, 02:37 AM (This post was last modified: 07-15-2016 02:38 AM by Eddie W. Shore.)
Post: #1
 Eddie W. Shore Senior Member Posts: 1,047 Joined: Dec 2013
(12C) Modulus
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, 06:32 PM (This post was last modified: 07-15-2016 07:00 PM by Dieter.)
Post: #2
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
RE: (12C) Modulus
(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.

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-18-2016, 10:12 PM
Post: #3
 bshoring Member Posts: 259 Joined: Dec 2013
RE: (12C) Modulus
(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.

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

Regards,
Bob
07-21-2016, 11:36 PM
Post: #4
 RobertM Member Posts: 73 Joined: Jul 2016
RE: (12C) Modulus
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-25-2016, 09:17 AM (This post was last modified: 07-25-2016 10:10 AM by Dieter.)
Post: #5
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
RE: (12C) Modulus
(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:46 AM (This post was last modified: 07-29-2016 05:40 PM by Dieter.)
Post: #6
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
RE: (12C) Modulus
(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-28-2016, 11:01 PM (This post was last modified: 07-28-2016 11:02 PM by bshoring.)
Post: #7
 bshoring Member Posts: 259 Joined: Dec 2013
RE: (12C) Modulus
(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.

Regards,
Bob
07-29-2016, 05:39 PM (This post was last modified: 07-29-2016 05:43 PM by Dieter.)
Post: #8
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
RE: (12C) Modulus
(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
 « Next Oldest | Next Newest »

User(s) browsing this thread: 1 Guest(s)