(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: 950 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,398 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.
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-18-2016, 10:12 PM
Post: #3
 bshoring Member Posts: 251 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.
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

Regards,
Bob
07-21-2016, 11:36 PM
Post: #4
 RobertM Member Posts: 66 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,398 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,398 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: 251 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,398 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)