Post Reply 
Base conversion (including fractional parts)
01-27-2017, 05:02 AM (This post was last modified: 01-27-2017 12:24 PM by Han.)
Post: #1
Base conversion (including fractional parts)
Started by this thread: http://hpmuseum.org/forum/thread-7585-post-67381.html

Code below is from the aforementioned thread.

Code:
EXPORT basecalc()
BEGIN
  local maxdigits:=20; // maximum number of digits for frac part

  local j,k,t,run:=1;
  local b1:=10;
  local b2:=16;
  local d:=0;
  local n:="";
  local ds:="";
  local r:=string(rand,1,12); // create a random CAS variable
  local var:="";
  local ipn:=""; // integer part of n
  local fpn:=""; // frac part of n
  
  local digits:="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

  k:=size(r)-2;
  var:="tmp" + right(r,k);


  while run do
    t:=input(
      { 
        { n, [2], { 15, 80, 0 } },
        { b1, [0], { 25, 25, 1 } },
        { b2, [0], { 70, 25, 1 } },
        { maxdigits, [0], {25,25, 2 } }
      },
      "Base Converter",
      { "n=", "base1=", "base2=", "digits=" },
      {
        "Enter the integer",
        "Enter the base of the integer n",
        "Enter the base to convert to",
        "Max allowable digits"
      }
    );

    if t then
      r:=var + ":={0,0}";
      CAS(EVAL(r));
      k:=size(n);
      if (k AND (b1 >= 2) AND (b2 <= 62)) then

        j:=instring(n,".");

        if j then
          if (j-1>0) then ipn:=left(n,j-1); end;
          if (k-j>0) then fpn:=right(n,k-j); end;
          k:=j-2;
        else
          ipn:=n;
          k:=size(n)-1;
        end;

        // k = largest exponent
        t:=size(ipn);
        for j from 1 to t do
          ds:=mid(ipn,j,1);
          d:=instring(digits,ds)-1;
          if ((d >= b1) OR (d < 0)) then msgbox("Invalid digit: " + ds); j:=-1; break; end;
          r:=var + "[1]:=" + var + "[1]+" + d + "*" + b1 + "^" + k;
          k:=k-1;
          CAS(EVAL(r));
        end;
        if (j == -1) then continue; end;

        t:=size(fpn);
        for j from 1 to t do
          ds:=mid(fpn,j,1);
          d:=instring(digits,ds)-1;
          if ((d >= b1) OR (d < 0)) then msgbox("Invalid digit: " + ds); j:=-1; break; end;
          r:=var + "[2]:=" + var + "[2]+" + d + "*" + b1 + "^" + k;
          k:=k-1;
          CAS(EVAL(r));
        end;
        if (j == -1) then continue; end;

        n:="";

        t:=size(ipn);
        if t then
          r:="ip(ln(" + var + "[1])/ln(" + b2 + ")))";
          k:=CAS(EVAL(r));
          for j from k downto 0 do
            r:="ip(" + var + "[1]/(" + b2 + "^" + j + "))";
            d:=CAS(EVAL(r));
            ds:=mid(digits,d+1,1);
            n:=n+ds;
            r:=var + "[1]:=" + var + "[1] - " + d + "*" + b2 + "^" + j;
            CAS(EVAL(r));
          end;
        end;

        t:=size(fpn);
        if t then
          n:=n+".";
          r:="numer(" + var + "[2])"; t:=CAS(EVAL(r));
          r:="denom(" + var + "[2])"; k:=CAS(EVAL(r));
          for j from 1 to maxdigits do
            r:="ip(" + var + "[2]*" + b2 + ")";
            d:=CAS(EVAL(r));
            r:=var + "[2]:=" + var + "[2]*" + b2 + "-" + d;
            CAS(EVAL(r));

            // floating point issue
            r:=var + "[2] < 0";
            if CAS(EVAL(r)) then
              r:=var + "[2]:=" + var + "[2]+1";
              CAS(EVAL(r));
              d:=d-1;
            end;
            ds:=mid(digits,d+1,1);
            n:=n+ds;
            r:=var + "[2] == 0";
            if CAS(EVAL(r)) then break; end;
          end;
        end;

        t:=b1;
        b1:=b2;
        b2:=t;

      else
        msgbox("Invalid input");
      end;

    else
      run:=0;
    end;

  end;

  r:="purge(" + var + ")";
  CAS(EVAL(r));
  return(0);
END;

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
01-27-2017, 08:57 PM
Post: #2
RE: Base conversion (including fractional parts)
Radix, Very good program


an idea

To start choosing the style

1: single [input / output] field (current)

2: two separate [input] / [output] fields, To view or compare conversion

3: an option with text (bases more known or useful)

BINARY 2
OCTAL 8
DECIMAL 10
DUDECIMAL 12
HEXADECIMAL 16
VIGECIMAL 20
SEXAGECIMAL 60
https://en.wikipedia.org/wiki/Radix

4: separate in the case of hexadecimal numbers the outputs in pairs for easier reading
FF 8F 0F

5: lowercase support ff8f0f
Find all posts by this user
Quote this message in a reply
01-27-2017, 10:19 PM
Post: #3
RE: Base conversion (including fractional parts)
(01-27-2017 08:57 PM)compsystems Wrote:  Radix, Very good program

I was not able to find a program named Radix in the HP Prime software library. Do you have a link?


Quote:an idea

To start choosing the style

1: single [input / output] field (current)

2: two separate [input] / [output] fields, To view or compare conversion

3: an option with text (bases more known or useful)

BINARY 2
OCTAL 8
DECIMAL 10
DUDECIMAL 12
HEXADECIMAL 16
VIGECIMAL 20
SEXAGECIMAL 60
https://en.wikipedia.org/wiki/Radix

4: separate in the case of hexadecimal numbers the outputs in pairs for easier reading
FF 8F 0F

I will leave these ideas for others to implement. I usually hate doing UI design :-)

Quote:5: lowercase support ff8f0f

Lower case letters are actually used as digits for bases 37 through 62, so this would cause a conflict if we were to use lower case letters as alternatives to capital letters. I suppose that we could allow for lower case letters for digits only in the cases where the base is 36 or less. A simple test of the base, along with a conversion to upper case would be more than sufficient. But again, this is a "UI" option I'll leave to folks who are not as lazy as myself. :-)

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
01-28-2017, 03:57 AM
Post: #4
RE: Base conversion (including fractional parts)
Radix synonymous of base =)

Base conversion is a port of BASECAL (rpn)? As a suggestion to separate the hp-prime code in sub-functions

PHP Code:
%%HPT(3)A(R)F(.);

@->
IB  Take either a binary or a real from the stack and return
@       
it in the base specified in BBASErounded off to IBFIX
@        places.

@
IB->  : Take an IB string from the stack and convert it to either
@        a binary number or a real.  If IBFIX is set to zeroit will
@        always return a binary number.  If IBFIX is set to somthing
@        other than zeroit will use return a real if the base-10
@        numver is less than 1E12.

@
IB2-> : Runs IB-> on the objects in level one and twoleaving their
@        order intact.

@
BBASE The current base. (2-62 is valid)

@
IBFIX Number of desired decimal places. (0 will force all calculations
@                                          to be carried out in binaries)

@->
IB2 Runs ->IB on the objects in level 1 and twoleaving their
@        order intact.


BASECALC by Ian Matthew Smith
Automatic decimal lengths added by Joe Horn
DIR

  BMTH 
create custom menu
    
\<< { Add \<< IB2\-> + \->IB \>> }
        { 
Sub \<< IB2\-> - \->IB \>> }
        { 
Mul \<< IB2\-> * \->IB \>> }
        { 
Div \<< IB2\-> / \->IB \>> }
      
BBASE "/" IBFIX + +
      { \<< 
B\->FIX 'BBASE' STO BMTH \>>
        \<< 
B\->FIX SWAP IB\-> SWAP 'BBASE' STO \->IB BMTH \>>
        \<< 
'IBFIX' STO BMTH \>> }
      
\->LIST CONV {
      \<< 
DUP
        
IF TYPE 2 ==
        
THEN IB\->
        
ELSE \->IB
        END
      
\>>
      \<< 
DUP
        
IF TYPE 0 ==
        
THEN R\->B
        
ELSE DUP
          
IF TYPE 10 ==
          
THEN B\->R
          END
        END
      
\>> } } \->LIST TMENU
    
\>>

  \->
IB
    
\<< DUP
      
IF TYPE 0 ==
      
THEN DUP FP SWAP IP R\->B
      
ELSE 0 SWAP
      END DUP
      
IF TYPE 10 ==
      
THEN RCWS SWAP "" SWAP 64 STWS
        
WHILE DUP B\->R
        REPEAT DUP BBASE DUP2 
/ * - BSTR SWAP
          B
\->R DUP SUB ROT SWAP BBASE /
        
END DROP SWAP STWS SWAP
        
IF DUP BBASE IBFIX ^ * <
        
THEN DROP
        
ELSE "" SWAP 1 IBFIX
          START
            
IF DUP 0 \=/
            
THEN BBASE DUP IP BSTR SWAP 1 DUP SUB ROT SWAP SWAP FP
            END
          NEXT DROP 
"." SWAP + +
        
END
      END
    
\>>

  
IB\->
    \<< 
DUP
      
IF TYPE 2 ==
      
THEN RCWS SWAP 64 STWS
        
IF DUP "." POS
        THEN DUP DUP 
"." POS SWAP DUP SIZE ROT 1 SWAP SUB
          SWAP DUP 
"." POS 1 1 SWAP SUB
        
ELSE "" SWAP
        END 
# 0d SWAP DUP SIZE 1 - 0 SWAP
        
FOR j DUP DUP SIZE j DUP SUB BSTR SWAP POS 1 # 1d
          
IF j 0 >
          
THEN BBASE 1 j
            START DUP ROT 
SWAP
            NEXT DROP
          END 
ROT SWAP
        NEXT DROP
        
IF DUP B\->R 1.E12 IBFIX AND
        
THEN B\->R
        END SWAP
        
IF DUP SIZE
        THEN 0 SWAP DUP SIZE 1 SWAP
          
FOR j DUP j j SUB BSTR SWAP POS 1 BBASE j NEG ^ * ROT SWAP
          NEXT DROP 
+
        ELSE 
DROP
        END SWAP STWS
      
ELSE
        IF 
DUP TYPE 0 == IBFIX NOT AND
        
THEN R\->B
        END
      END
    
\>>

  
IB2\->
    \<< 
IB\-> SWAP IB\-> SWAP
    
\>>

  
BBASE 16

  IBFIX 0

  
\->IB2
    
\<< \->IB SWAP \->IB SWAP
    
\>>
  
B\->FIX  this tiny routine was tacked on by Joe Horn
    
\<< 2 MAX 62 MIN 12 OVER LOG IP 'IBFIX' STO
    
\>>

  
BSTR
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
END 
Find all posts by this user
Quote this message in a reply
01-28-2017, 03:40 PM
Post: #5
RE: Base conversion (including fractional parts)
(01-28-2017 03:57 AM)compsystems Wrote:  Base conversion is a port of BASECAL (rpn)?

No, I just wrote the program based on my own understanding of base conversions and what Joe was requesting.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
01-29-2017, 12:29 PM
Post: #6
RE: Base conversion (including fractional parts)
What utility have the conversion of real numbers between different bases? I have only used conversion between integers.

About the program, please separate the UI from the functions, to create custom UI
Find all posts by this user
Quote this message in a reply
Post Reply 




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