Πέμπτη, 1 Νοεμβρίου 2018

Convert from any base to any base



Module Checkit {
      Conv2dec=lambda (n$, frombase=10, dp$=".") -> {
           neg=left$(n$,1)="-": if neg then n$=mid$(n$,2)
           if instr(n$, dp$)>0 then {
                 n2$=Piece$(n$,dp$,2)
                 n$=Piece$(n$, dp$,1)
           } else n2$=""
           n0=0
           l1=len(n$)+1
           For i=len(n$) to 1
                 dig$=Mid$(n$,l1-i,1)
                 dig=asc(dig$)-48
                 if dig$>"9" then dig-=7
                 if dig>=frombase then error "not in base:"+frombase
                 n0+=dig*frombase^(i-1)
           next i
           if n2$<>"" then {
              For i=1 to len(n2$)
                 dig$=Mid$(n2$,i,1)
                 dig=asc(dig$)-48
                 if dig$>"9" then dig-=7
                 if dig>=frombase then error "not in base:"+frombase
                 n0+=dig/frombase^i
              Next i
           }
           if neg then n0-!
           =n0
      }
      Conv2Any$=Lambda$ (dec, tobase=10, dp$=".", prec=16) -> {
           a$=""
           neg=false
           if dec<0 then neg=true
           dec=abs(dec)
           n2=frac(dec)
           if dec=0 then {
                 a$="0"
           } else {
                 do {
                        n=dec mod tobase
                        if n>=10 then n+=7
                        a$=chr$(n+48)+a$
                        dec=dec div tobase
                  } until dec==0
            }
            if n2<>0 then {
                 a$+=dp$
                 prec--
                 do {
                      prec--
                      dec=n2*tobase
                      n2=frac(dec)
                      dec-=n2
                      n2=round(n2)
                      if dec>=10 then dec+=7
                      a$+=chr$(dec+48)
                 } until n2=0 or prec<0
            }
            if neg then {="-"+a$} else =a$
      }
      Rem : Locale 1033 ' use . for all print out for decimal point
      Print Conv2dec("10111.01011",2); " => ";Conv2Any$(23.34375,2)
      Print Conv2Any$(11.90625, 2); " => "; Conv2dec("1011.11101",2)
      \\ using , for decimal point
      Print Conv2Any$(Conv2dec("1011,11101",2, ","), 10, ",")
      Print 12312321.1212
      clipboard Conv2Any$(12312321.1212, 2)
      \\ using . for 1033 locale
      Print Str$(Conv2Dec(Conv2Any$(12312321.1212, 2), 2), 1033)="12312321.1211853"
      Print Str$(Conv2Dec(Conv2Any$(12312321.1212, 2,,52), 2), 1033) ="12312321.1212"
}
Checkit