Post Reply 
HP 49G: Challenge - Truncate a Long Real
07-06-2015, 07:49 PM
Post: #1
HP 49G: Challenge - Truncate a Long Real
Here is my attempt to truncate a long real imitating the real function TRNC.

For long real input

%% 5.12345678901
%% 5

the programme returns

%% 5.12345

& for input

%% 5.12345678901
%% -5

returns

%% 5.1234.

I find it hard to believe this is the most economical way to do it.

Can you suggest a less long-winded programme?

Code:

::
  CK2&Dispatch
  # 3F3F
  ::
    DUP%%0=_
    casedrop
    ::
      DUP
      ::
        DUP%%0=_
        ?SEMI
        DUP
        %%ABS
        %%/
      ;
      SWAP
      %%ABS
      %%INT
      %%*
    ;
    DUP
    %%ABS
    %%.5
    %%+
    %%INT
    SWAP
    ::
      DUP%%0=_
      ?SEMI
      DUP
      %%ABS
      %%/
    ;
    %%*
    DUP
    %%0>
    DUP
    4PICK
    DUP
    %%INT
    %%-
    %%0=
    AND
    case2DROP
    ?SKIP
    %%1+_
    %%ABS
    SWAPDUP
    %%ABS
    %%LN
    %%10
    %%LN
    %%/
    %%INT
    SWAP
    %%ABS
    %%10
    OVER
    %%ABS
    %%LN
    %%10
    %%LN
    %%/
    %%INT
    %%^
    %%/
    %%10
    4ROLL
    %%^
    %%*
    %%INT
    %%ABS
    %%10
    OVER
    %%ABS
    %%LN
    %%10
    %%LN
    %%/
    %%INT
    %%^
    %%/
    %%10
    ROT
    %%^
    %%*
  ;
;
Find all posts by this user
Quote this message in a reply
07-07-2015, 06:33 AM
Post: #2
RE: HP 49G: Challenge - Truncate a Long Real
Hi Gerald,

you may use strings for truncating a long real, e.g:

5.12345678901
ENTER
->STR

this converts your real into the string "5.12345678901"

now enter:

1
ENTER
5
ENTER
SUB
ENTER

this truncates your string after the 5th charachter: "5.123"

The last step is to convert the string back to a real:

STR->
ENTER

This leaves 5.123 on Level 1 of the stack.
The only problem is that you need to know the number of charachters to the left of the decimal point because the SUB command strictly counts from left to right.

Hope this helps

Best regards

Karl
Find all posts by this user
Quote this message in a reply
07-07-2015, 06:38 AM
Post: #3
RE: HP 49G: Challenge - Truncate a Long Real
Thank you, Karl-Ludwig, for your suggestion.

However, for input

%% 7.12345678901234

%% 13

your method fails.
Find all posts by this user
Quote this message in a reply
07-07-2015, 12:25 PM
Post: #4
RE: HP 49G: Challenge - Truncate a Long Real
Hi Gerald,

I just tried the example you mentioned. 13 decimal places from 7.12345678901234 should leave 7.1234567890123 but because the ->STR routine converts only 11 decimal places to string, the maximum is 11 decimal places. If you can avoid the ->STR routine by inputing the number as string, this limitation of the ->STR routine would not occur.

Best regards

Karl
Find all posts by this user
Quote this message in a reply
07-07-2015, 12:35 PM
Post: #5
RE: HP 49G: Challenge - Truncate a Long Real
I'm not sure you know what a long real is.

Try this:

Place

1.234

on the stack & apply the command ->S2 (that's right arrow S 2), you should see

"% 1.234
@"

This is how a real number decompiles.

Now apply the command ASM to the last result & you have 1.234 again.

If you change

"% 1.234
@"

to

"%% 1.23456789012345
@"

& apply ASM you will now see a long real on the stack, having 15 rather than 12 digits.
Find all posts by this user
Quote this message in a reply
07-07-2015, 01:17 PM
Post: #6
RE: HP 49G: Challenge - Truncate a Long Real
(07-06-2015 07:49 PM)Gerald H Wrote:  Here is my attempt to truncate a long real imitating the real function TRNC.
I find it hard to believe this is the most economical way to do it.

Can you suggest a less long-winded programme?

How about using →H and H→ to convert to string?

→H on 1.23456789012345 will give you:

"55920000005432109876543210"

The first 5 digits are the prolog, the next 5 are the exponent (0 in this case), and then you have your 15 digits, and the sign digit at the end.

Truncating to a certain number of significant digits is easy, all you have to do is to replace the appropriate digits with zero and run H→.
Truncating to a number of decimals after the dot can be tricky, you need to "read" the exponent to know where the dot would be, then replace the proper digits with zeros.
Find all posts by this user
Quote this message in a reply
07-07-2015, 01:54 PM
Post: #7
RE: HP 49G: Challenge - Truncate a Long Real
Interesting approach, Claudio.

How would you deal with

%% 5.678E1234

to 3 decimal places? The mantissa & exponent are nicely separated in this representation, after ->H you have to work them out yourself.

& remember the 3 could be negative, just as in the TRNC function for normal reals.

Your suggestion may be a good approach....until you work out the details I think it will probably end up longer than my effort.

I will be very happy to be proven wrong.
Find all posts by this user
Quote this message in a reply
07-07-2015, 03:53 PM
Post: #8
RE: HP 49G: Challenge - Truncate a Long Real
(07-07-2015 01:54 PM)Gerald H Wrote:  Interesting approach, Claudio.

How would you deal with

%% 5.678E1234

to 3 decimal places? The mantissa & exponent are nicely separated in this representation, after ->H you have to work them out yourself.

& remember the 3 could be negative, just as in the TRNC function for normal reals.

Your suggestion may be a good approach....until you work out the details I think it will probably end up longer than my effort.

I will be very happy to be proven wrong.

OK, challenge accepted. Here it is (in UserRPL). Looks a lot longer because of the comments:

Code:

<<
SWAP ->H 0.
-> N S TPOS <<
    @@ N=NUMBER OF DIGITS, S=STRING REPRESENTATION
    @@ TPOS = POSITION OF TRUNCATION

    IF N 0 < THEN

    @@ WHEN N<0, TOTAL SIGNIFICANT FIGURES IS THE EASY CASE

          15. N + 'TPOS' STO 
    ELSE
    @@ N>=0, N IS SIGNIFICANT FIGURES AFTER THE DECIMAL DOT

          @ WE NEED THE EXPONENT
          S 6. 10. SUB
          "339204000000000" SWAP + "0" + H->
          @ HERE WE HAVE THE EXPONENT IN TEN'S COMPLEMENT AS A REAL
          @ CONVERT IT TO A NEGATIVE NUMBER
           DUP IF 50000. > THEN 100000. - END

          @ NOW LET'S COMPUTE THE POSITION OF THE LAST DIGIT WE WANT
          14. SWAP - N -

          'TPOS' STO
   END

   @@ NOW WE KNOW THE POSITION OF TRUNCATION, JUST  DO THE MAGIC

   @ IF MORE THAN 15, THE NUMBER WOULD BE ALL ZEROS, KEEP AT 15
    TPOS IF 15. > THEN 15. 'TPOS' STO END

    IF TPOS 0. > THEN
                             @ SEPARATE PROLOG AND EXPONENT
                             S 1. 10. SUB
                            @ PAD WITH ZEROES AS NEEDED
                            "000000000000000" 1. TPOS SUB
                            @ NOW ADD THE DIGITS WE WANT TO KEEP
                            S 11. TPOS + 26. SUB
                            @ AND PUT IT ALL BACK TOGETHER
                            + + 
    ELSE 
    @ NOTHING TO DO, RESTORE THE ORIGINAL NUMBER
    S 
    END
    H->

>>

>>
Find all posts by this user
Quote this message in a reply
07-07-2015, 04:48 PM (This post was last modified: 07-07-2015 05:54 PM by Gerald H.)
Post: #9
RE: HP 49G: Challenge - Truncate a Long Real
Bravo, Claudio!

Your programme works!

I include a code box for your programme to display it more clearly.

I haven't fully tested the programme yet, however for input

1.41421356237309E-12345

5.

it returns

0E-12345

Correct, but I prefer

0E0

Your programme is 435.5 Bytes while my latest version is 110 Bytes.

Code:

« SWAP ->H 0. -> N S TPOS

  «
    IF N 0 <
    THEN 15. N + 'TPOS' STO
    ELSE S 6. 10. SUB "339204000000000" SWAP + "0" + H-> DUP
      IF 50000. >
      THEN 100000. -
      END 14. SWAP - N - 'TPOS' STO
    END TPOS
    IF 15. >
    THEN 15. 'TPOS' STO
    END
    IF TPOS 0. >
    THEN S 1. 10. SUB "000000000000000" 1. TPOS SUB S 11. TPOS + 26. SUB + +
    ELSE S
    END H->
  »
»
Find all posts by this user
Quote this message in a reply
07-07-2015, 05:48 PM
Post: #10
RE: HP 49G: Challenge - Truncate a Long Real
(07-07-2015 04:48 PM)Gerald H Wrote:  Bravo, Claudio!

Your programme works!

I include a code box for your programme to display it more clearly.

I haven't fully tested the programme yet, however for input

1.41421356237309E-12345

5.

it returns

0E-12345

Correct, but I prefer

0E0

Your programme is 435.5 Bytes while my latest version is 110 Bytes.

Yes, one consequence of direct manipulation of digits is that zero becomes denormalized. It shouldn't cause any problems when operating on it, and can easily be solved by adding %% 0. to the final result (but you can't do that in userRPL, you'd have to port the code to sysRPL).
It should be easy to port to sysRPL to save a few more bytes (or at least eliminate the local variables), but where the idea will shine is in Saturn ASM, as the manipulation of digits can be done directly in a register instead of a string, which would make it extremely small and fast. also reading the exponent is trivial in ASM, but requires quite some work in userRPL.
Find all posts by this user
Quote this message in a reply
07-17-2015, 07:58 AM
Post: #11
RE: HP 49G: Challenge - Truncate a Long Real
Here my improved version of the truncation programme for long reals, replicating the built in TRNC function for reals.

So the winner of the challenge is me, unless someone publishes a better programme, an extremely unlikely eventuality.

Code:

::
  CK2&Dispatch
  # 3F3F
  ::
    %%>%
    %0
    RNDXY
    %>%%
    DUP
    %%0<
    IT
    ::
      %%ABS
      OVER
      ::
        DUP%%0=_
        ?SEMI
        %%ABS
        %%LN
        %%10
        %%LN
        %%/
        %%INT
      ;
      %%1+_
      %%-
    ;
    %%10
    SWAP
    %%^
    DUPUNROT
    %%*
    DUP
    ::
      DUP%%0=_
      ?SEMI
      DUP
      %%ABS
      %%/
    ;
    SWAP
    %%ABS
    %%INT
    %%*
    SWAP%%/
  ;
;
Find all posts by this user
Quote this message in a reply
Post Reply 




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