Generalised floating point multiplication: Difference between revisions

m
m (→‎{{header|Phix}}: added b_sub)
m (→‎{{header|Wren}}: Minor tidy)
 
(19 intermediate revisions by 4 users not shown)
Line 58:
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-2.3.3 algol68g-2.3.3].}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
'''File: Template.Big_float.Multiplication.a68'''<langsyntaxhighlight lang="algol68">##########################################
# TASK CODE #
# Actual generic mulitplication operator #
Line 116:
 
OP *:= = (REF DIGITS lhs, DIGIT arg)DIGITS: lhs := lhs * INITDIGITS arg;
</langsyntaxhighlight>'''File: Template.Balanced_ternary_float.Base.a68'''<langsyntaxhighlight lang="algol68">PR READ "Template.Big_float_BCD.Base.a68" PR # [[rc:Generalised floating point addition]] #
 
################################################################
Line 151:
OD;
out SHR (UPB s-point)
);</langsyntaxhighlight>'''File: test.Balanced_ternary_float.Multiplication.a68'''<langsyntaxhighlight lang="algol68">#!/usr/local/bin/a68g --script #
####################################################################
# A program to test arbitrary length floating point multiplication #
Line 200:
printf($l$)
OD
)</langsyntaxhighlight>'''Output:'''
<pre>
a = +523.23914037494284407864655 +-0++0+.+-0++0+
Line 238:
</pre>
 
=={{header|PhixGo}}==
{{trans|Phix}}
Note regarding requirement #5: While this meets my definition of "reasonably efficient",
In the interests of brevity many of the comments and all of the commented-out code has been omitted.
it should not shock anyone that this kind of "string maths" which works digit-by-digit
<syntaxhighlight lang="go">package main
and uses repeated addition (eg *999 performs 27 additions) could easily be 10,000 times
slower than raw hardware or a carefully optimised library such as gmp. However this does
offer perfect accuracy in any given base, whereas gmp, for all it's brilliance, can hold
0.1 accurate to several million decimal places, but just never quite exact.
 
import (
<lang Phix>-- demo\rosetta\Generic_multiplication.exw
"fmt"
constant MAX_DP = 81
"log"
"math"
"strings"
)
 
const (
constant binary = "01",
maxdp ternary = "012",81
binary balancedternary = "-0+01",
ternary decimal = "0123456789012",
hexadecimalbalancedTernary = "0123456789ABCDEF-0+",
decimal septemvigesimal = "0123456789ABCDEFGHIJKLMNOPQ0123456789",
hexadecimal = "0123456789ABCDEF"
-- heptavintimal = "0123456789ABCDEFGHKMNPRTVXZ", -- ??
septemVigesimal = "0123456789ABCDEFGHIJKLMNOPQ"
-- wonky_donkey_26 = "0ABCDEFGHIJKLMNOPQRSTUVWXY",
balancedBase27 = "ZYXWVUTSRQPON0ABCDEFGHIJKLM"
-- wonky_donkey_27 = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ",
base37 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
balanced_base27 = "ZYXWVUTSRQPON0ABCDEFGHIJKLM",
)
base37 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
--
--Note: I have seen some schemes where balanced-base-27 uses
--==== the same character set as septemvigesimal, with 'D'
-- representing 0, and wonky_donkey_27 with 'M'==0(!).
-- These routines do not support that directly, except
-- (perhaps) via a simple mapping on all inputs/outputs.
-- It may be possible to add a defaulted parameter such
-- as zero='0' - left as an exercise for the reader.
-- Admittedly that balanced_base27 is entirely my own
-- invention, just for this specific task.
--
 
/* helper functions */
function b2dec(string b, alphabet)
 
--
--func convertchangeByte(s string, bidx backint, intoc a normal (decimalbyte) atom,string {
bytes := []byte(s)
-- eg b2dec("+0-",balancedternary) yields 8
bytes[idx] = c
--
atomreturn res = 0string(bytes)
}
integer base = length(alphabet),
 
zdx = find('0',alphabet)
func removeByte(s string, idx int) string {
bool signed = (zdx=1 and b[1]='-')
le := len(s)
if signed then b = b[2..$] end if
integer lenbytes := length[]byte(bs),
copy(bytes[idx:], bytes[idx+1:])
ndp = find('.',b)
ifreturn ndp!=string(bytes[0 then: le-1])
}
b[ndp..ndp] = "" -- remove '.'
 
ndp = len-ndp
func insertByte(s string, idx int, c byte) string {
end if
forle i:=1 to lengthlen(bs) do
t res := base*res+findmake(b[i]byte,alphabet le+1)-zdx
endcopy(t, fors)
copy(t[idx+1:], t[idx:])
if ndp!=0 then res /= power(base,ndp) end if
t[idx] = c
if signed then res = -res end if
return string(t)
}
 
func prependByte(s string, c byte) string {
le := len(s)
bytes := make([]byte, le+1)
copy(bytes[1:], s)
bytes[0] = c
return string(bytes)
}
 
func abs(i int) int {
if i < 0 {
return -i
}
return i
}
 
// converts Phix indices to Go
func gIndex(pIndex, le int) int {
if pIndex < 0 {
return pIndex + le
}
return pIndex - 1
}
 
func getCarry(digit, base int) int {
if digit > base {
return 1
} else if digit < 1 {
return -1
}
return 0
}
 
// convert string 'b' to a decimal floating point number
func b2dec(b, alphabet string) float64 {
res := 0.0
base := len(alphabet)
zdx := strings.IndexByte(alphabet, '0') + 1
signed := zdx == 1 && b[0] == '-'
if signed {
b = b[1:]
}
le := len(b)
ndp := strings.IndexByte(b, '.') + 1
if ndp != 0 {
b = removeByte(b, ndp-1) // remove decimal point
ndp = le - ndp
}
for i := 1; i <= len(b); i++ {
idx := strings.IndexByte(alphabet, b[i-1]) + 1
res = float64(base)*res + float64(idx) - float64(zdx)
}
if ndp != 0 {
res /= math.Pow(float64(base), float64(ndp))
}
if signed {
res = -res
}
return res
}
end function
 
// string 'b' can be balanced or unbalanced
function negate(string b, alphabet)
func negate(b, alphabet string) string {
--
if alphabet[0] == '0' {
-- negate b (can be balanced or unbalanced)
if b != "0" {
--
if alphabetb[10] == '0-' then{
-- traditional: add/remove a leading '-' b = b[1:]
-- eg "-123" <==> "123"} else {
if b! ="0" thenprependByte(b, '-')
if b[1]='-' then}
b = b[2..$]}
} else else{
for i := 1; i <= len(b); =i++ "-"&b{
end if b[i-1] != '.' {
idx := strings.IndexByte(alphabet, b[i-1]) + 1
end if
gi := gIndex(-idx, len(alphabet))
else
b = changeByte(b, i-1, alphabet[gi])
-- balanced: mirror [non-0] digits
-- eg "-0+" (ie -8) <==> "+0-" (ie +8)}
for i=1 to length(b) do}
}
if b[i]!='.' then
b[i] = alphabet[-find(b[i],alphabet)]
end if
end for
end if
return b
}
end function
 
func bTrim(b string) string {
function b_trim(string b)
// trim trailing ".000"
-- (common code)
idx := strings.IndexByte(b, '.') + 1
-- trim trailing ".000"
if find('.',b)idx then!= 0 {
b = trim_tailstrings.TrimRight(trim_tailstrings.TrimRight(b,' "0'"),' ".'")
end if}
--// trim leading zeroes,zeros but not "0.nnn" -> ".nnn"
for len(b) > 1 && b[0] == '0' && b[1] != '.' {
-- [hence we cannot use the standard trim_head()]
while length(b)>1 and b[1] ='0' and b[21:]!='.' do
b = b[2..$]}
end while
return b
}
end function
 
// for balanced number systems only
function b_carry(integer digit, base, idx, string n, alphabet)
func bCarry(digit, base, idx int, n, alphabet string) (int, string) {
-- (common code, for balanced number systems only)
integer carry := iffgetCarry(digit>, base?+1:iff(digit<1?-1:0))
if carry then!= 0 {
for i := idx; toi 0>= by1; i--1 do{
if n[i-1] != '.' then{
integer k := findstrings.IndexByte(alphabet, n[i-1],alphabet) + 1
if k < base then{
n[i] = changeByte(n, i-1, alphabet[k+1])
exitbreak
end if}
n[ = changeByte(n, i]=-1, alphabet[10])
end if}
end for}
digit -= base * carry
end if}
return {digit, n}
}
end function
 
function// convert a b2b(string n,from alphabet, to alphabet2)
func b2b(n, alphabet, alphabet2 string) string {
--
res, m := "0", ""
-- convert a string from alphabet to alphabet2,
if n != "0" {
-- eg b2b("8",decimal,balancedternary) yields "+0-",
base := len(alphabet)
-- & b2b("+0-",balancedternary,decimal) yields "8",
base2 := len(alphabet2)
--
zdx := strings.IndexByte(alphabet, '0') + 1
string res = "0", m = ""
zdx2 := strings.IndexByte(alphabet2, '0') + 1
if n!="0" then
integervar basecarry, =q, length(alphabet)r, digit int
idx := strings.IndexByte(alphabet, n[0]) + 1
base2 = length(alphabet2),
negative := (zdx == 1 && n[0] == '-') || (zdx != find('0',alphabet1 && idx < zdx),
if negative {
zdx2 = find('0',alphabet2),
carryn = 0, q, rnegate(n, digitalphabet)
}
bool negative = ((zdx=1 and n[1]='-') or
ndp := strings.IndexByte(n, '.') + 1
(zdx!=1 and find(n[1],alphabet)<zdx))
if negative then nndp != negate(n,alphabet) end0 if{
integer ndp n, m = find('.'n[0:ndp-1], n)[ndp:]
if ndp!=0 then}
{n,m} = {n[1..ndp-1],n[ndp+1..$]}
end if
res = ""
whilefor lengthlen(n) do> 0 {
q = 0
for i := 1; toi length<= len(n); i++ do{
digit = strings.IndexByte(alphabet, n[i-1]) + 1 - zdx
--q this= isq*base a+ digit-by-digit divide (/mod) loop
--r eg= forabs(q) hex->decimal% we would want:base2
--digit = this loop/modremabs("FFFF",10q)/base2 --> "1999" rem+ 5,zdx
--if q this< loop/modrem("1999",10)0 --> "28F" rem 3,{
-- this loop/modrem("28F",10) digit--> "41" rem 5,
-- this loop/modrem("41",10) --> "6" rem 5,}
--if zdx this!= loop/modrem("6",10)1 --> "0" rem 6,{
-- ==> res:="65535" (in 5digit, fulln iterations= overbCarry(digit, base, i-1, n, alphabet).
--}
digitn = findchangeByte(n[, i]-1, alphabet)[digit-zdx1])
q = q*base+digit
r = mod(q,base2)
digit = floor(q/base2)+zdx
if zdx!=1 then
{digit,n} = b_carry(digit,base,i-1,n,alphabet)
end if
n[i] = alphabet[digit]
q = r
end for}
r += zdx2
if zdx2 != 1 then{
r += carry
carry = iffgetCarry(r>, base2?+1:iff(r<1?-1:0))
r -= base2 * carry
end if}
res = prependByte(res, alphabet2[r-1]&res)
n = trim_headstrings.TrimLeft(n,' "0'")
end while}
if carry then!= 0 {
res = prependByte(res, alphabet2[carry+zdx2-1]&res)
end if}
if lengthlen(m) then> 0 {
res &+= '".'"
ndp = 0
if zdx != 1 then{
--lm convert fraction to unbalanced, to simplify the:= len(other-basem) multiply.
integer lmalphaNew := lengthbase37[0:len(malphabet)]
string alphanewm = base37[1..lengthb2b(m, alphabet, alphaNew)]
m = b2bstrings.Repeat(m"0",alphabet,alphanew) lm-- len(nb:m)) no+ fractional part!)m
malphabet = repeat('0',lm-length(m))&m -- zero-pad if requiredalphaNew
alphabet = alphanew
zdx = 1
end if}
whilefor lengthlen(m) and> 0 && ndp <MAX_DP domaxdp {
q = 0
for i :=length len(m); toi >= 1; by i--1 do{
digit = strings.IndexByte(alphabet, m[i-1]) + 1 - zdx
--q this+= is a digit-by-digit multiply* loopbase2
--r eg= forabs(q)%base [.]"1415"+ decimal->decimal wezdx
--q would repeatedly multiply by 10, giving/= base
--if 1q and< "4150",0 then 4 and "1500", then{
-- 1 and "5000", then 5 and "0000". Weq--
-- strip zeroes between each output digit}
--m &= obviouslychangeByte(m, normallyi-1, alphabet in!=out.[r-1])
--}
digit = find(m[i],alphabet)-zdx
q += digit*base2
r = mod(q,base)+zdx
q = floor(q/base)
m[i] = alphabet[r]
end for
digit = q + zdx2
if zdx2 != 1 then{
{digit, res} = b_carrybCarry(digit, base2,length len(res), res, alphabet2)
end if}
res &+= string(alphabet2[digit-1])
m = trim_tailstrings.TrimRight(m,' "0'")
ndp += 1+
end while}
end if}
res = b_trimbTrim(res)
if negative then res = negate(res,alphabet2) end if{
res = negate(res, alphabet2)
end if
}
}
return res
}
end function
 
// convert 'd' to a string in the specified base
function atm2b(atom d, string alphabet)
func float2b(d float64, alphabet string) string {
--
base := len(alphabet)
-- convert d to a string in the specified base,
zdx := strings.Index(alphabet, "0") + 1
-- eg atm2b(65535,hexadecimal) => "FFFF"
carry := 0
--
neg := d < 0
-- As a standard feature of phix, you can actually specify
if neg {
-- d in any number base between 2 and 36, eg 0(13)168 is
d = -d
-- equivalent to 255 (see test\t37misc.exw for more), but
}
-- not (yet) in balanced number bases, or with fractions,
res := ""
-- except (of course) for normal decimal fractions.
whole := int(d)
--
d -= float64(whole)
-- Note that eg b2b("-436.436",decimal,balancedternary) is
for {
-- more acccurate that atm2b(-436.436,balancedternary) due
ch := whole%base + zdx
-- to standard IEEE 754 floating point limitations.
if zdx != 1 {
-- For integers, discrepancies only creep in for values
-- outside the range +/-9,007,199,254,740,992 (on 32-bit).
-- However, this is much simpler and faster than b2b().
--
integer base = length(alphabet),
zdx = find('0',alphabet),
carry = 0
bool neg = d<0
if neg then d = -d end if
string res = ""
integer whole = floor(d)
d -= whole
while true do
integer ch = mod(whole,base) + zdx
if zdx!=1 then
ch += carry
carry = iffgetCarry(ch>, base?+1:iff(ch<1?-1:0))
ch -= base * carry
end if}
res = prependByte(res, alphabet[ch-1]&res)
whole /= floor(whole/base)
if whole ==0 then exit end0 if{
end while break
if carry then }
}
res = alphabet[carry+zdx]&res
if carry != 0 {
res = prependByte(res, alphabet[carry+zdx-1])
carry = 0
end if}
if d != 0 then{
res &+= '".'"
integer ndp := 0
whilefor d != 0 and&& ndp <MAX_DP domaxdp {
d *= float64(base)
integer digit := floorint(d) + zdx
d -= float64(digit)
if zdx != 1 then{
{digit, res} = b_carrybCarry(digit, base,length len(res), res, alphabet)
end if}
res &+= string(alphabet[digit-1])
ndp += 1+
end while}
end if}
if neg then res = negate(res,alphabet) end if{
res = negate(res, alphabet)
}
return res
}
end function
 
func bAdd(a, b, alphabet string) string {
-- negative numbers in addition and subtraction
base := len(alphabet)
-- (esp. non-balanced) are treated as follows:
zdx := strings.IndexByte(alphabet, '0') + 1
-- for -ve a: (-a)+b == b-a; (-a)-b == -(a+b)
var carry, da, db, digit int
-- for -ve b: a+(-b) == a-b; a-(-b) == a+b
if zdx == 1 {
-- for a>b: a-b == -(b-a) [avoid running off end]
if a[0] == '-' {
 
forward function b_sub return bSub(stringb, negate(a, balphabet), alphabet)
}
 
if b[0] == '-' {
function b_add(string a, b, alphabet)
integer base = length return bSub(a, negate(b, alphabet), alphabet)
zdx = find('0',alphabet),}
}
carry = 0, da, db, digit
adt := strings.IndexByte(a, '.') + 1
if zdx=1 then
bdt := strings.IndexByte(b, '.') + 1
-- (let me know if you can fix this for me!)
-- if a[1]='-'adt or b[1]!='-' then ?9/0 end|| ifbdt --!= +ve0 only{
if a[1]adt !='-' then -- (-a)+b ==0 b-a{
returnadt b_sub(b,negate= len(a,alphabet),alphabet) - adt + 1
end if gi := gIndex(-adt, len(a))
if b[1]='-' then -- a+(-b) == removeByte(a-b, gi)
}
return b_sub(a,negate(b,alphabet),alphabet)
end if bdt != 0 {
bdt = len(b) - bdt + 1
end if
integer adt gi := findgIndex('.'-bdt,a len(b)),
bdtb = findremoveByte('.',b, gi)
if adt or bdt then}
if bdt > adt {
-- remove the '.'s and zero-pad the shorter as needed
-- (thereafter treata them+= asstrings.Repeat("0", two whole integersbdt-adt)
-- eg "1.23"+"4.5" -> "123"+"450" (leaving adt==2)
if adt then adt = length(a)-adt+1; a[-adt..-adt] = "" end if
if bdt then bdt = length(b)-bdt+1; b[-bdt..-bdt] = "" end if
if bdt>adt then
a &= repeat('0',bdt-adt)
adt = bdt
elsif} else if adt > bdt then{
b &+= repeatstrings.Repeat('"0'", adt-bdt)
end if}
end if}
if lengthlen(a) <length len(b) then{
{a, b} = {b, a} -- ensure b is the shorter
end if}
for i := -1; toi >= -lengthlen(a); by i--1 do{
daif =i iff(i< -lengthlen(a)?0:find(a[i],alphabet)-zdx) {
da = 0
db = iff(i<-length(b)?0:find(b[i],alphabet)-zdx)
} else {
da = strings.IndexByte(alphabet, a[len(a)+i]) + 1 - zdx
}
if i < -len(b) {
db = 0
} else {
db = strings.IndexByte(alphabet, b[len(b)+i]) + 1 - zdx
}
digit = da + db + carry + zdx
carry = iffgetCarry(digit>, base?+1:iff(digit<1?-1:0))
a[i] = changeByte(a, i+len(a), alphabet[digit-carry*base-1])
if i < -lengthlen(b) and&& carry ==0 then exit end0 if{
end for break
if carry then }
}
a = alphabet[carry+zdx]&a
end if carry != 0 {
a = prependByte(a, alphabet[carry+zdx-1])
if adt then
}
a[-adt+1..-adt] = "."
end if adt != 0 {
a gi := b_trimgIndex(-adt+1, len(a))
a = insertByte(a, gi, '.')
}
a = bTrim(a)
return a
}
end function
 
functionfunc a_smalleraSmaller(string a, b, alphabet string) bool {
-- return true if len(a) is smaller than!= len(b) {
log.Fatal("strings should be equal in length")
-- if not balanced then both are +ve
}
if length(a)!=length(b) then ?9/0 end if -- sanity check
for i := 1; toi length<= len(a); i++ do{
integer da := findstrings.IndexByte(alphabet, a[i-1],alphabet), + 1
db := findstrings.IndexByte(alphabet, b[i-1],alphabet), + 1
if da != db c = compare(a,b){
if c!=0 then return c<0da end< ifdb
end for }
}
return false -- (=, which is not <)
return false
end function
}
 
functionfunc b_subbSub(string a, b, alphabet string) string {
integer base := lengthlen(alphabet),
zdx := findstrings.IndexByte(alphabet, '0',alphabet), + 1
var carry = 0, da, db, digit int
if zdx == 1 then{
if a[10] == '-' then -- (-a)-b == -(a+b){
return negate(b_addbAdd(negate(a, alphabet), b, alphabet), alphabet)
end if}
if b[10] == '-' then -- a-(-b) == a+b{
return b_addbAdd(a, negate(b, alphabet), alphabet)
end if}
end if}
integer adt := find('strings.',Index(a), ".") + 1
bdt := findstrings.Index('b, ".',b") + 1
if adt or!= 0 || bdt then!= 0 {
if adt != 0 {
-- remove the '.'s and zero-pad the shorter as needed
-- (thereafter treatadt them= aslen(a) two- wholeadt integers)+ 1
-- eg "1.23"+"4.5" -> "123"+"450"gi := gIndex(leaving-adt, adt==2len(a))
if adt then adt a = lengthremoveByte(a, gi)-adt+1; a[-adt..-adt] = "" end if
}
if bdt then bdt = length(b)-bdt+1; b[-bdt..-bdt] = "" end if
if bdt>adt then!= 0 {
abdt &= repeatlen('0',bdt-adtb) - bdt + 1
gi := gIndex(-bdt, len(b))
b = removeByte(b, gi)
}
if bdt > adt {
a += strings.Repeat("0", bdt-adt)
adt = bdt
elsif} else if adt > bdt then{
b &+= repeatstrings.Repeat('"0'", adt-bdt)
end if}
end if}
bool bNegate := false
if len(a) < len(b) || (len(a) == len(b) && aSmaller(a, b, alphabet)) {
if length(a)<length(b)
or (length(a)=length(b) and a_smaller(a,b,alphabet)) then
bNegate = true
{a, b} = {b, a} -- ensure b is the shorter/smaller
end if}
for i := -1; toi >= -lengthlen(a); by i--1 do{
daif =i iff(i< -lengthlen(a)?0:find(a[i],alphabet)-zdx) {
da = 0
db = iff(i<-length(b)?0:find(b[i],alphabet)-zdx)
digit} =else da - (db + carry) + zdx{
da = strings.IndexByte(alphabet, a[len(a)+i]) + 1 - zdx
carry = digit<=0
}
a[i] = alphabet[digit+carry*base]
if i < -lengthlen(b) and carry=0 then exit end if{
end for db = 0
if carry then } else {
?9/0 --db should= havestrings.IndexByte(alphabet, setb[len(b)+i]) bNegate+ above...1 - zdx
end if }
digit = da - db - carry + zdx
if adt then
a[-adt+1..-adt]carry = "."0
end if digit <= 0 {
a carry = b_trim(a)1
if bNegate then }
a = negatechangeByte(a, i+len(a), alphabet[digit+carry*base-1])
if i < -len(b) && carry == 0 {
end if
break
}
}
if carry != 0 {
log.Fatal("carry should be zero")
}
if adt != 0 {
gi := gIndex(-adt+1, len(a))
a = insertByte(a, gi, '.')
}
a = bTrim(a)
if bNegate {
a = negate(a, alphabet)
}
return a
}
end function
 
functionfunc b_mulbMul(string a, b, alphabet string) string {
integer basezdx := lengthstrings.IndexByte(alphabet), '0') + 1
dpa := strings.IndexByte(a, '.') + 1
zdx = find('0',alphabet),
dpb dpa := findstrings.IndexByte(b, '.',a), + 1
ndp dpb := find('.',b),0
if dpa ndp != 0 {
if dpa then ndp += lengthlen(a) -dpa; a[dpa..dpa] = "" end if
a = removeByte(a, dpa-1)
if dpb then ndp += length(b)-dpb; b[dpb..dpb] = "" end if
}
string pos = a, res = "0"
if zdxdpb !=1 then0 {
--ndp balanced+= numberlen(b) - systemsdpb
string negb = negateremoveByte(posb,alphabet dpb-1)
}
for i=length(b) to 1 by -1 do
pos, res := a, "0"
integer m = find(b[i],alphabet)-zdx
if zdx != 1 while m do{
// balanced number systems
res = b_add(res,iff(m<0?neg:pos),alphabet)
neg m +:= iffnegate(m<0?+1:-1pos, alphabet)
for i := len(b); endi while>= 1; i-- {
posm &:= '0'strings.IndexByte(alphabet, b[i-1]) + 1 - zdx
negfor &m != '0' {
end for temp, temp2 := pos, -1
if m < 0 {
else
-- non-balanced (normal) number systems temp = neg
bool negative temp2 = false1
if a[1]='-' then a = a[2..$]; negative = true end if}
if b[1]='-' then b = b[2..$]; negative res = not negativebAdd(res, endtemp, ifalphabet)
for i=length(b) to 1 by -1 do m += temp2
integer m = find(b[i],alphabet)-zdx}
whilepos m>0+= do"0"
neg res += b_add(res,pos,alphabet)"0"
m -= 1}
} else end while{
// non-balanced number pos &= '0'systems
endnegative for:= false
if negative then resa[0] == negate(res,alphabet) end'-' if{
end if a = a[1:]
negative = true
if ndp then
res[-ndp..-ndp-1] = "."}
end if b[0] == '-' {
res b = b_trim(res)b[1:]
negative = !negative
}
for i := len(b); i >= 1; i-- {
m := strings.IndexByte(alphabet, b[i-1]) + 1 - zdx
for m > 0 {
res = bAdd(res, pos, alphabet)
m--
}
pos += "0"
}
if negative {
res = negate(res, alphabet)
}
}
if ndp != 0 {
gi := gIndex(-ndp, len(res))
res = insertByte(res, gi, '.')
}
res = bTrim(res)
return res
}
end function
 
func multTable() {
fmt.Println("multiplication table")
fmt.Println("====================")
fmt.Printf("* |")
for j := 1; j <= 12; j++ {
fj := float64(j)
fmt.Printf(" #%s %3s |", float2b(fj, hexadecimal), float2b(fj, balancedTernary))
}
for i := 1; i <= 27; i++ {
fi := float64(i)
a := float2b(fi, balancedTernary)
fmt.Printf("\n%-2s|", float2b(fi, septemVigesimal))
for j := 1; j <= 12; j++ {
if j > i {
fmt.Printf(" |")
} else {
fj := float64(j)
b := float2b(fj, balancedTernary)
m := bMul(a, b, balancedTernary)
fmt.Printf(" %6s |", m)
}
}
}
fmt.Println()
}
 
func test(name, alphabet string) {
a := b2b("+-0++0+.+-0++0+", balancedTernary, alphabet)
b := b2b("-436.436", decimal, alphabet)
c := b2b("+-++-.+-++-", balancedTernary, alphabet)
d := bSub(b, c, alphabet)
r := bMul(a, d, alphabet)
fmt.Printf("%s\n%s\n", name, strings.Repeat("=", len(name)))
fmt.Printf(" a = %.16g %s\n", b2dec(a, alphabet), a)
fmt.Printf(" b = %.16g %s\n", b2dec(b, alphabet), b)
fmt.Printf(" c = %.16g %s\n", b2dec(c, alphabet), c)
fmt.Printf("a*(b-c) = %.16g %s\n\n", b2dec(r, alphabet), r)
}
 
func main() {
-- [note 1] not surprisingly, the decimal output is somewhat cleaner/shorter when
test("balanced ternary", balancedTernary)
-- the decimal string inputs for a and c are used, whereas tests 1/2/5/7
test("balanced base 27", balancedBase27)
-- (the 3-based ones) look much better with all ternary string inputs.
test("decimal", decimal)
test("binary", binary)
test("ternary", ternary)
test("hexadecimal", hexadecimal)
test("septemvigesimal", septemVigesimal)
multTable()
}</syntaxhighlight>
 
{{out}}
procedure test(string name, alphabet)
<pre>
--string a = b2b("523.2391403749428",decimal,alphabet), -- [see note 1]
balanced ternary
string a = b2b("+-0++0+.+-0++0+",balancedternary,alphabet),
================
b = b2b("-436.436",decimal,alphabet),
-- b a = b2b("523.2391403749428 +-0++-0--+.-+-0+-00+0++-",balancedternary,alphabet),
b = -436.4359999999999 -++-0--.--0+-00+++-0-+---0-+0++++0--0000+00-+-+--+0-0-00--++0-+00---+0+-+++0+-0----0++
-- c = b2b("65.26748971193416",decimal,alphabet), -- [see note 1]
c = b2b("65.26748971193416 +-++-.+-++-",balancedternary,alphabet),
a*(b-c) = -262510.9026799813 ----000-0+0+.0+0-0-00---00--0-0+--+--00-0++-000++0-000-+0+-----+++-+-0+-+0+0++0+0-++-++0+---00++++
d = b_add(b,c,alphabet),
 
r = b_mul(a,d,alphabet)
balanced base 27
printf(1,"%s\n%s\n",{name,repeat('=',length(name))})
================
printf(1," a = %.16g %s\n",{b2dec(a,alphabet),a})
a = 523.2391403749428 AUJ.FLI
printf(1," b = %.16g %s\n",{b2dec(b,alphabet),b})
b = -436.4359999999999 NKQ.YFDFTYSMHVANGXPVXHIZJRJWZD0PBGFJAEBAKOZODLY0ITEHPQLSQSGLFZUINATKCIKUVMWEWJMQ0COTS
printf(1," c = %.16g %s\n",{b2dec(c,alphabet),c})
c = 65.26748971193416 BK.GF
-- printf(1," d = %.16g %s\n",{b2dec(d,alphabet),d})
a*(b-c) = -262510.9026799812 ZVPJ.CWNYQPEENDVDPNJZXKFGCLHKLCX0YIBOMETHFWWBTVUFAH0SEZMTBJDCRRAQIQCAWMKXSTPYUXYPK0LODUO
printf(1,"a*(b-c) = %.16g %s\n\n",{b2dec(r,alphabet),r})
 
end procedure
decimal
test("balanced ternary", balancedternary)
=======
test("balanced base 27", balanced_base27)
a = 523.2391403749428 523.239140374942844078646547782350251486053955189757658893461362597165066300868770004
test("decimal", decimal)
b = -436.436 -436.436
test("binary", binary)
c = 65.26748971193413 65.267489711934156378600823045267489711934156378600823045267489711934156378600823045
test("ternary", ternary)
a*(b-c) = -262510.9026799813 -262510.90267998140903693918986303277315826215892262734715612833785876513103053772667101895163734826631742752252837097627017862754285047634638652268078676654605120794218
test("hexadecimal", hexadecimal)
 
test("septemvigesimal", septemvigesimal)</lang>
binary
The printed decimal output is inherently limited to IEEE 754 precision, hence I
======
deliberately limited output (%.16g) because it is silly to try and go any higher,
a = 523.2391403749427 1000001011.001111010011100001001101101110011000100001011110100101001010100100000111001000111
whereas the output from b_mul() is actually perfectly accurate, see [note 1] above.
b = -436.436 -110110100.011011111001110110110010001011010000111001010110000001000001100010010011011101001
c = 65.26748971193416 1000001.01000100011110100011010010101100110001100000111010111111101111001001001101111101
a*(b-c) = -262510.9026799814 -1000000000101101110.111001110001011000001001000001101110011111011100000100000100001000101011100011110010110001010100110111001011101001010000001110110100111110001101000000001111110101
 
ternary
=======
a = 523.2391403749428 201101.0201101
b = -436.4360000000002 -121011.102202211210021110012111201022222000202102010100101200200110122011122101110212
c = 65.26748971193416 2102.02102
a*(b-c) = -262510.9026799813 -111100002121.2201010011100110022102110002120222120100001221111011202022012121122001201122110221112
 
hexadecimal
===========
a = 523.2391403749427 20B.3D384DB9885E94A90723EF9CBCB174B443E45FFC41152FE0293416F15E3AC303A0F3799ED81589C62
b = -436.436 -1B4.6F9DB22D0E5604189374BC6A7EF9DB22D0E5604189374BC6A7EF9DB22D0E5604189374BC6A7EF9DB2
c = 65.26748971193416 41.447A34ACC60EBFBC937D5DC2E5A99CF8A021B641511E8D2B3183AFEF24DF5770B96A673E28086D905
a*(b-c) = -262510.9026799814 -4016E.E7160906E7DC10422DA508321819F4A637E5AEE668ED5163B12FCB17A732442F589975B7F24112B2E8F6E95EAD45803915EE26D20DF323D67CAEEC75D7BED68AA34E02F2B492257D66F028545FB398F60E
 
septemvigesimal
===============
a = 523.2391403749428 JA.6C9
b = -436.4359999999999 -G4.BKML7C5DJ8Q0KB39AIICH4HACN02OJKGPLOPG2D1MFBQI6LJ33F645JELD7I0Q6FNHG88E9M9GE3QO276
c = 65.26748971193416 2B.76
a*(b-c) = -262510.9026799812 -D92G.OA1C42LM0N8N30HDAFKJNEIFEOB0BHP1DM6ILA9P797KPJ05MCE6OGMO54Q3I3NQ9DGB673C8BC2FQF1N82
 
multiplication table
====================
* | #1 + | #2 +- | #3 +0 | #4 ++ | #5 +-- | #6 +-0 | #7 +-+ | #8 +0- | #9 +00 | #A +0+ | #B ++- | #C ++0 |
1 | + | | | | | | | | | | | |
2 | +- | ++ | | | | | | | | | | |
3 | +0 | +-0 | +00 | | | | | | | | | |
4 | ++ | +0- | ++0 | +--+ | | | | | | | | |
5 | +-- | +0+ | +--0 | +-+- | +0-+ | | | | | | | |
6 | +-0 | ++0 | +-00 | +0-0 | +0+0 | ++00 | | | | | | |
7 | +-+ | +--- | +-+0 | +00+ | ++0- | +---0 | +--++ | | | | | |
8 | +0- | +--+ | +0-0 | ++-- | ++++ | +--+0 | +-0+- | +-+0+ | | | | |
9 | +00 | +-00 | +000 | ++00 | +--00 | +-000 | +-+00 | +0-00 | +0000 | | | |
A | +0+ | +-+- | +0+0 | ++++ | +-0-- | +-+-0 | +0--+ | +000- | +0+00 | ++-0+ | | |
B | ++- | +-++ | ++-0 | +--0- | +-00+ | +-++0 | +00-- | +0+-+ | ++-00 | ++0+- | +++++ | |
C | ++0 | +0-0 | ++00 | +--+0 | +-+-0 | +0-00 | +00+0 | ++--0 | ++000 | ++++0 | +--0-0 | +--+00 |
D | +++ | +00- | +++0 | +-0-+ | +-++- | +00-0 | +0+0+ | ++0-- | +++00 | +---++ | +--+0- | +-0-+0 |
E | +--- | +00+ | +---0 | +-0+- | +0--+ | +00+0 | ++-0- | ++0++ | +---00 | +--+-- | +-0-0+ | +-0+-0 |
F | +--0 | +0+0 | +--00 | +-+-0 | +0-+0 | +0+00 | ++0-0 | ++++0 | +--000 | +-0--0 | +-00+0 | +-+-00 |
G | +--+ | ++-- | +--+0 | +-+0+ | +000- | ++--0 | ++0++ | +---+- | +--+00 | +-00-+ | +-+--- | +-+0+0 |
H | +-0- | ++-+ | +-0-0 | +0--- | +00++ | ++-+0 | ++++- | +--00+ | +-0-00 | +-0+0- | +-+0-+ | +0---0 |
I | +-00 | ++00 | +-000 | +0-00 | +0+00 | ++000 | +---00 | +--+00 | +-0000 | +-+-00 | +-++00 | +0-000 |
J | +-0+ | +++- | +-0+0 | +0-++ | ++--- | +++-0 | +--0-+ | +-0-0- | +-0+00 | +-+00+ | +0--+- | +0-++0 |
K | +-+- | ++++ | +-+-0 | +000- | ++-0+ | ++++0 | +--+-- | +-00-+ | +-+-00 | +-+++- | +0-0++ | +000-0 |
L | +-+0 | +---0 | +-+00 | +00+0 | ++0-0 | +---00 | +--++0 | +-0+-0 | +-+000 | +0--+0 | +00--0 | +00+00 |
M | +-++ | +--0- | +-++0 | +0+-+ | ++0+- | +--0-0 | +-0-0+ | +-+--- | +-++00 | +0-0++ | +0000- | +0+-+0 |
N | +0-- | +--0+ | +0--0 | +0++- | +++-+ | +--0+0 | +-000- | +-+-++ | +0--00 | +00--- | +00+0+ | +0++-0 |
O | +0-0 | +--+0 | +0-00 | ++--0 | ++++0 | +--+00 | +-0+-0 | +-+0+0 | +0-000 | +000-0 | +0+-+0 | ++--00 |
P | +0-+ | +-0-- | +0-+0 | ++-0+ | +---0- | +-0--0 | +-0+++ | +-+++- | +0-+00 | +00+-+ | +0++-- | ++-0+0 |
Q | +00- | +-0-+ | +00-0 | ++0-- | +---++ | +-0-+0 | +-+-+- | +0--0+ | +00-00 | +0+-0- | ++---+ | ++0--0 |
10| +000 | +-000 | +0000 | ++000 | +--000 | +-0000 | +-+000 | +0-000 | +00000 | +0+000 | ++-000 | ++0000 |
</pre>
 
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">using Formatting
import Base.BigInt, Base.BigFloat, Base.print, Base.+, Base.-, Base.*
 
abstract type BalancedBaseDigitArray end
 
mutable struct BalancedTernary <: BalancedBaseDigitArray
dig::Vector{Int8}
p::Int
BalancedTernary(arr::Vector, i) = new(Int8.(arr), i)
end
 
const MAX_PRECISION = 81
 
function BalancedTernary(s::String)
if (i = findfirst(x -> x == '.', s)) != nothing
p = length(s) - i
s = s[1:i-1] * s[i+1:end]
else
p = 0
end
b = BalancedTernary([c == '-' ? -1 : c == '0' ? 0 : 1 for c in s], p) # 2
end
 
function BalancedTernary(n::Integer) # 1, 3
if n < 0
return -BalancedTernary(-n)
elseif n == 0
return BalancedTernary([0], 0)
else
return canonicalize!(BalancedTernary(reverse(digits(n, base=3)), 0))
end
end
BalancedTernary() = BalancedTernary(0)
 
function BalancedTernary(x::Real) # 1, 3
if x < 0
return -BalancedTernary(-x)
end
arr = reverse(digits(BigInt(round(x * big"3.0"^MAX_PRECISION)), base=3))
return canonicalize!(BalancedTernary(arr, MAX_PRECISION))
end
 
function String(b::BalancedTernary) # 3
canonicalize!(b)
s = String([['-', '0', '+'][c + 2] for c in b.dig])
if b.p > 0
if b.p < length(s)
s = s[1:end-b.p] * "." * s[end-b.p+1:end]
elseif b.p == length(s)
s = "0." * s
else
s = "0." * "0"^(b.p - length(s)) * s
end
end
return s
end
 
function BigInt(b::BalancedTernary)
canonicalize!(b)
if b.p > 0
throw(InexactError("$(b.p) places after decimal point"))
end
return sum(t -> BigInt(3)^(t[1] - 1) * t[2], enumerate(reverse(b.dig))) # 3
end
 
BigFloat(b::BalancedTernary) = BigInt(BalancedTernary(b.dig, 0)) / big"3.0"^(b.p)
 
function canonicalize!(b::BalancedTernary)
for i in length(b.dig):-1:1
if b.dig[i] > 1
b.dig[i] -= 3
if i == 1
pushfirst!(b.dig, 1)
else
b.dig[i - 1] += 1
end
elseif b.dig[i] < -1
b.dig[i] += 3
if i == 1
pushfirst!(b.dig, -1)
else
b.dig[i - 1] -= 1
end
end
end
if (i = findfirst(x -> x != 0, b.dig)) != nothing
if i > 1
b.dig = b.dig[i:end]
end
else
b.dig = [0]
end
if b.p > 0 && (i = findlast(x -> x != 0, b.dig)) != nothing
removable = min(b.p, length(b.dig) - i)
b.dig = b.dig[1:end-removable]
b.p -= removable
end
return b
end
 
# The following should work with any base number where dig, p are a similar array and Int
# and the proper constructors, canon, and conversion routines are defined # 6
 
Base.print(io::IO, b::BalancedBaseDigitArray) = print(io, String(b))
 
function +(b1::T, b2::T) where T <: BalancedBaseDigitArray # 4
if all(x -> x == 0, b1.dig)
return deepcopy(b2)
elseif all(x -> x == 0, b2.dig)
return deepcopy(b1)
end
ldigits1 = length(b1.dig) - b1.p
arr = b1.dig[1:ldigits1]
ldigits2 = length(b2.dig) - b2.p
arr2 = b2.dig[1:ldigits2]
if (i = ldigits1 - ldigits2) > 0
arr2 = [zeros(Int8, i); arr2]
elseif i < 0
arr = [zeros(Int8, -i); arr]
end
if (i = b1.p - b2.p) > 0
arr = [arr; b1.dig[ldigits1+1:end]]
arr2 = [arr2; b2.dig[ldigits2+1:end]; zeros(Int8, i)]
elseif i < 0
arr = [arr; b1.dig[ldigits1+1:end]; zeros(Int8, -i)]
arr2 = [arr2; b2.dig[ldigits2+1:end]]
else
arr = [arr; b1.dig[ldigits1+1:end]]
arr2 = [arr2; b2.dig[ldigits2+1:end]]
end
arr .+= arr2
return canonicalize!(T(arr, max(b1.p, b2.p)))
end
 
-(b1::T) where T <: BalancedBaseDigitArray = T(b1.dig .* -1, b1.p) # 4
-(b1::T, b2::T) where T <: BalancedBaseDigitArray = +(b1, -b2) # 4
 
function *(b1::T, b2::T) where T <: BalancedBaseDigitArray # 4
len = length(b2.dig)
bsum = T()
for i in len:-1:1
bsum += T([b1.dig .* b2.dig[i]; zeros(Int8, len - i)], 0)
end
bsum.p = b1.p + b2.p
return canonicalize!(bsum)
end
 
function code_reuse_task(T::Type)
a = T("+-0++0+.+-0++0+")
b = T(-436.436)
c = T("+-++-.+-++-")
println(" a = ", a, " = ", format(BigFloat(a)))
println(" b = ", b, " = ", format(BigFloat(b)))
println(" c = ", c, " = ", format(BigFloat(c)))
println("\na * (b - c) = ", String(a * (b - c)), "\n = ", format(BigFloat(a * (b - c))))
 
println("\n Multiplication 27 X 12")
println(" x|+ (1) |+- (2) |+0 (3) |++ (4) |+-- (5)|+-0 (6)|+-+ (7)|+0- (8)|+e+-(9)|+0+(10)|++-(11)|++0(12)|")
for i in 1:27
print(lpad(i, 2), "|")
for j in 1:12
print(lpad(String(T(i * j)), 7), "|")
end
print("\n")
end
end
 
code_reuse_task(BalancedTernary)
</syntaxhighlight>{{out}}
<pre>
a = +-0++0+.+-0++0+ = 523.23914
b = -++-0--.--0+-00+++-0-+---0-+0++++0--++++0-+0+-0+0+-000-0----+0--0---+-000++--++-+-0--0-+ = -436.436
c = +-++-.+-++- = 65.26749
 
a * (b - c) = ----000-0+0+.0+0-0-00---00--0-0+--+0-0+0++-+-0--0--+0-++-0-+00-++0-0-0+++--0-+0--+-++-+-+-++-+0+-+-+
= -262510.90268
 
Multiplication 27 X 12
x|+ (1) |+- (2) |+0 (3) |++ (4) |+-- (5)|+-0 (6)|+-+ (7)|+0- (8)|+e+-(9)|+0+(10)|++-(11)|++0(12)|
1| +| +-| +0| ++| +--| +-0| +-+| +0-| +00| +0+| ++-| ++0|
2| +-| ++| +-0| +0-| +0+| ++0| +---| +--+| +-00| +-+-| +-++| +0-0|
3| +0| +-0| +00| ++0| +--0| +-00| +-+0| +0-0| +000| +0+0| ++-0| ++00|
4| ++| +0-| ++0| +--+| +-+-| +0-0| +00+| ++--| ++00| ++++| +--0-| +--+0|
5| +--| +0+| +--0| +-+-| +0-+| +0+0| ++0-| ++++| +--00| +-0--| +-00+| +-+-0|
6| +-0| ++0| +-00| +0-0| +0+0| ++00| +---0| +--+0| +-000| +-+-0| +-++0| +0-00|
7| +-+| +---| +-+0| +00+| ++0-| +---0| +--++| +-0+-| +-+00| +0--+| +00--| +00+0|
8| +0-| +--+| +0-0| ++--| ++++| +--+0| +-0+-| +-+0+| +0-00| +000-| +0+-+| ++--0|
9| +00| +-00| +000| ++00| +--00| +-000| +-+00| +0-00| +0000| +0+00| ++-00| ++000|
10| +0+| +-+-| +0+0| ++++| +-0--| +-+-0| +0--+| +000-| +0+00| ++-0+| ++0+-| ++++0|
11| ++-| +-++| ++-0| +--0-| +-00+| +-++0| +00--| +0+-+| ++-00| ++0+-| +++++| +--0-0|
12| ++0| +0-0| ++00| +--+0| +-+-0| +0-00| +00+0| ++--0| ++000| ++++0| +--0-0| +--+00|
13| +++| +00-| +++0| +-0-+| +-++-| +00-0| +0+0+| ++0--| +++00| +---++| +--+0-| +-0-+0|
14| +---| +00+| +---0| +-0+-| +0--+| +00+0| ++-0-| ++0++| +---00| +--+--| +-0-0+| +-0+-0|
15| +--0| +0+0| +--00| +-+-0| +0-+0| +0+00| ++0-0| ++++0| +--000| +-0--0| +-00+0| +-+-00|
16| +--+| ++--| +--+0| +-+0+| +000-| ++--0| ++0++| +---+-| +--+00| +-00-+| +-+---| +-+0+0|
17| +-0-| ++-+| +-0-0| +0---| +00++| ++-+0| ++++-| +--00+| +-0-00| +-0+0-| +-+0-+| +0---0|
18| +-00| ++00| +-000| +0-00| +0+00| ++000| +---00| +--+00| +-0000| +-+-00| +-++00| +0-000|
19| +-0+| +++-| +-0+0| +0-++| ++---| +++-0| +--0-+| +-0-0-| +-0+00| +-+00+| +0--+-| +0-++0|
20| +-+-| ++++| +-+-0| +000-| ++-0+| ++++0| +--+--| +-00-+| +-+-00| +-+++-| +0-0++| +000-0|
21| +-+0| +---0| +-+00| +00+0| ++0-0| +---00| +--++0| +-0+-0| +-+000| +0--+0| +00--0| +00+00|
22| +-++| +--0-| +-++0| +0+-+| ++0+-| +--0-0| +-0-0+| +-+---| +-++00| +0-0++| +0000-| +0+-+0|
23| +0--| +--0+| +0--0| +0++-| +++-+| +--0+0| +-000-| +-+-++| +0--00| +00---| +00+0+| +0++-0|
24| +0-0| +--+0| +0-00| ++--0| ++++0| +--+00| +-0+-0| +-+0+0| +0-000| +000-0| +0+-+0| ++--00|
25| +0-+| +-0--| +0-+0| ++-0+| +---0-| +-0--0| +-0+++| +-+++-| +0-+00| +00+-+| +0++--| ++-0+0|
26| +00-| +-0-+| +00-0| ++0--| +---++| +-0-+0| +-+-+-| +0--0+| +00-00| +0+-0-| ++---+| ++0--0|
27| +000| +-000| +0000| ++000| +--000| +-0000| +-+000| +0-000| +00000| +0+000| ++-000| ++0000|
</pre>
 
=={{header|Phix}}==
Note regarding requirement #5: While this meets my definition of "reasonably efficient",
it should not shock anyone that this kind of "string maths" which works digit-by-digit
and uses repeated addition (eg *999 performs 27 additions) could easily be 10,000 times
slower than raw hardware or a carefully optimised library such as gmp. However this does
offer perfect accuracy in any given base, whereas gmp, for all it's brilliance, can hold
0.1 accurate to several million decimal places, but just never quite exact.
 
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Generic_multiplication.exw</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAX_DP</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">81</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">binary</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"01"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">ternary</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"012"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">balancedternary</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"-0+"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">decimal</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0123456789"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">hexadecimal</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0123456789ABCDEF"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">septemvigesimal</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0123456789ABCDEFGHIJKLMNOPQ"</span><span style="color: #0000FF;">,</span>
<span style="color: #000080;font-style:italic;">-- heptavintimal = "0123456789ABCDEFGHKMNPRTVXZ", -- ??
-- wonky_donkey_26 = "0ABCDEFGHIJKLMNOPQRSTUVWXY",
-- wonky_donkey_27 = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ",</span>
<span style="color: #000000;">balanced_base27</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ZYXWVUTSRQPON0ABCDEFGHIJKLM"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">base37</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</span>
<span style="color: #000080;font-style:italic;">--
--Note: I have seen some schemes where balanced-base-27 uses
--==== the same character set as septemvigesimal, with 'D'
-- representing 0, and wonky_donkey_27 with 'M'==0(!).
-- These routines do not support that directly, except
-- (perhaps) via a simple mapping on all inputs/outputs.
-- It may be possible to add a defaulted parameter such
-- as zero='0' - left as an exercise for the reader.
-- Admittedly that balanced_base27 is entirely my own
-- invention, just for this specific task.
--</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">b2dec</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- convert string b back into a normal (decimal) atom,
-- eg b2dec("+0-",balancedternary) yields 8
--</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">zdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">signed</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">signed</span> <span style="color: #008080;">then</span> <span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ndp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ndp</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ndp</span><span style="color: #0000FF;">..</span><span style="color: #000000;">ndp</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #000080;font-style:italic;">-- remove '.'</span>
<span style="color: #000000;">ndp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">len</span><span style="color: #0000FF;">-</span><span style="color: #000000;">ndp</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">*</span><span style="color: #000000;">res</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ndp</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">/=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">base</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ndp</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">signed</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">res</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- negate b (can be balanced or unbalanced)
--</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- traditional: add/remove a leading '-'
-- eg "-123" &lt;==&gt; "123"</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">"0"</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"-"</span><span style="color: #0000FF;">&</span><span style="color: #000000;">b</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">else</span>
<span style="color: #000080;font-style:italic;">-- balanced: mirror [non-0] digits
-- eg "-0+" (ie -8) &lt;==&gt; "+0-" (ie +8)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[-</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">b</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">b_trim</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- (common code)
-- trim trailing ".000"</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim_tail</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">trim_tail</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">),</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">-- trim leading zeroes, but not "0.nnn" -&gt; ".nnn"
-- [hence we cannot use the standard trim_head()]</span>
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)></span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">and</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">b</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">b_carry</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- (common code, for balanced number systems only)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">></span><span style="color: #000000;">base</span><span style="color: #0000FF;">?+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digit</span><span style="color: #0000FF;"><</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">idx</span> <span style="color: #008080;">to</span> <span style="color: #000000;">0</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #008000;">'.'</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;"><</span><span style="color: #000000;">base</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">*</span><span style="color: #000000;">carry</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">b2b</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet2</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- convert a string from alphabet to alphabet2,
-- eg b2b("8",decimal,balancedternary) yields "+0-",
-- & b2b("+0-",balancedternary,decimal) yields "8",
--</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">"0"</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">base2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">zdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">zdx2</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet2</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">q</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">digit</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">negative</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">((</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span>
<span style="color: #0000FF;">(</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">negative</span> <span style="color: #008080;">then</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ndp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ndp</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">ndp</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ndp</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$]}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">--
-- this is a digit-by-digit divide (/mod) loop
-- eg for hex-&gt;decimal we would want:
-- this loop/modrem("FFFF",10) --&gt; "1999" rem 5,
-- this loop/modrem("1999",10) --&gt; "28F" rem 3,
-- this loop/modrem("28F",10) --&gt; "41" rem 5,
-- this loop/modrem("41",10) --&gt; "6" rem 5,
-- this loop/modrem("6",10) --&gt; "0" rem 6,
-- ==&gt; res:="65535" (in 5 full iterations over n).
--</span>
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span>
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">q</span><span style="color: #0000FF;">*</span><span style="color: #000000;">base</span><span style="color: #0000FF;">+</span><span style="color: #000000;">digit</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">/</span><span style="color: #000000;">base2</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">zdx</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_carry</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">n</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">zdx2</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx2</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">carry</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">></span><span style="color: #000000;">base2</span><span style="color: #0000FF;">?+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;"><</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">base2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">carry</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">r</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">res</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim_head</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">+</span><span style="color: #000000;">zdx2</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'.'</span>
<span style="color: #000000;">ndp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- convert fraction to unbalanced, to simplify the (other-base) multiply.</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lm</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">alphanew</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base37</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)]</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b2b</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphanew</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (nb: no fractional part!)</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lm</span><span style="color: #0000FF;">-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">))&</span><span style="color: #000000;">m</span> <span style="color: #000080;font-style:italic;">-- zero-pad if required</span>
<span style="color: #000000;">alphabet</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphanew</span>
<span style="color: #000000;">zdx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ndp</span><span style="color: #0000FF;"><</span><span style="color: #000000;">MAX_DP</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">--
-- this is a digit-by-digit multiply loop
-- eg for [.]"1415" decimal-&gt;decimal we
-- would repeatedly multiply by 10, giving
-- 1 and "4150", then 4 and "1500", then
-- 1 and "5000", then 5 and "0000". We
-- strip zeroes between each output digit
-- & obviously normally alphabet in!=out.
--</span>
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span>
<span style="color: #000000;">q</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">digit</span><span style="color: #0000FF;">*</span><span style="color: #000000;">base2</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">zdx</span>
<span style="color: #000000;">q</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">q</span><span style="color: #0000FF;">/</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">r</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">q</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">zdx2</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx2</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_carry</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base2</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">),</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">alphabet2</span><span style="color: #0000FF;">[</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">trim_tail</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ndp</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">negative</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet2</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">atm2b</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- convert d to a string in the specified base,
-- eg atm2b(65535,hexadecimal) =&gt; "FFFF"
--
-- As a standard feature of phix, you can actually specify
-- d in any number base between 2 and 36, eg 0(13)168 is
-- equivalent to 255 (see test\t37misc.exw for more), but
-- not (yet) in balanced number bases, or with fractions,
-- except (of course) for normal decimal fractions.
--
-- Note that eg b2b("-436.436",decimal,balancedternary) is
-- more acccurate that atm2b(-436.436,balancedternary) due
-- to standard IEEE 754 floating point limitations.
-- For integers, discrepancies only creep in for values
-- outside the range +/-9,007,199,254,740,992 (on 32-bit).
-- However, this is much simpler and faster than b2b().
--</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">zdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">neg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">d</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">neg</span> <span style="color: #008080;">then</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">d</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">whole</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">whole</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">whole</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">zdx</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">carry</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #000000;">base</span><span style="color: #0000FF;">?+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;"><</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">base</span><span style="color: #0000FF;">*</span><span style="color: #000000;">carry</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">res</span>
<span style="color: #000000;">whole</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">whole</span><span style="color: #0000FF;">/</span><span style="color: #000000;">base</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">whole</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">+</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">res</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'.'</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ndp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ndp</span><span style="color: #0000FF;"><</span><span style="color: #000000;">MAX_DP</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">base</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">zdx</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">digit</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_carry</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">,</span><span style="color: #000000;">base</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">),</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">ndp</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">neg</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">-- negative numbers in addition and subtraction
-- (esp. non-balanced) are treated as follows:
-- for -ve a: (-a)+b == b-a; (-a)-b == -(a+b)
-- for -ve b: a+(-b) == a-b; a-(-b) == a+b
-- for a&gt;b: a-b == -(b-a) [avoid running off end]</span>
<span style="color: #008080;">forward</span> <span style="color: #008080;">function</span> <span style="color: #000000;">b_sub</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">b_add</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">zdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">da</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">db</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">digit</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (-a)+b == b-a</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">b_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- a+(-b) == a-b</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">b_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">adt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">bdt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">adt</span> <span style="color: #008080;">or</span> <span style="color: #000000;">bdt</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- remove the '.'s and zero-pad the shorter as needed
-- (thereafter treat them as two whole integers)
-- eg "1.23"+"4.5" -&gt; "123"+"450" (leaving adt==2)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">adt</span> <span style="color: #008080;">then</span> <span style="color: #000000;">adt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">;</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bdt</span> <span style="color: #008080;">then</span> <span style="color: #000000;">bdt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">;</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bdt</span><span style="color: #0000FF;">></span><span style="color: #000000;">adt</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">adt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bdt</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">adt</span><span style="color: #0000FF;">></span><span style="color: #000000;">bdt</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">-</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)<</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- ensure b is the shorter</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #0000FF;">-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">da</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;"><-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">0</span><span style="color: #0000FF;">:</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">db</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;"><-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">0</span><span style="color: #0000FF;">:</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">da</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">db</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">carry</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">zdx</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">></span><span style="color: #000000;">base</span><span style="color: #0000FF;">?+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">digit</span><span style="color: #0000FF;"><</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">-</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">*</span><span style="color: #000000;">base</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">carry</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">+</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">a</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">adt</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">a</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"."</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">a</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">a_smaller</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- return true if a is smaller than b
-- if not balanced then both are +ve</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)!=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- sanity check</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">da</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">db</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">compare</span><span style="color: #0000FF;">(</span><span style="color: #000000;">da</span><span style="color: #0000FF;">,</span><span style="color: #000000;">db</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">c</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #000080;font-style:italic;">-- (=, which is not &lt;)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">b_sub</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">zdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">da</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">db</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">digit</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (-a)-b == -(a+b)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- a-(-b) == a+b</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">b_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">adt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">bdt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">adt</span> <span style="color: #008080;">or</span> <span style="color: #000000;">bdt</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- remove the '.'s and zero-pad the shorter as needed
-- (thereafter treat them as two whole integers)
-- eg "1.23"+"4.5" -&gt; "123"+"450" (leaving adt==2)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">adt</span> <span style="color: #008080;">then</span> <span style="color: #000000;">adt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">;</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bdt</span> <span style="color: #008080;">then</span> <span style="color: #000000;">bdt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">;</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bdt</span><span style="color: #0000FF;">></span><span style="color: #000000;">adt</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">adt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">bdt</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">adt</span><span style="color: #0000FF;">></span><span style="color: #000000;">bdt</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">&=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">-</span><span style="color: #000000;">bdt</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">bNegate</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)<</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">a_smaller</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">bNegate</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">}</span> <span style="color: #000080;font-style:italic;">-- ensure b is the shorter/smaller</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #0000FF;">-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">da</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;"><-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">0</span><span style="color: #0000FF;">:</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">db</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;"><-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)?</span><span style="color: #000000;">0</span><span style="color: #0000FF;">:</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">digit</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">da</span> <span style="color: #0000FF;">-</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">db</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">carry</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">zdx</span>
<span style="color: #000000;">carry</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">digit</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">0</span>
<span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">[</span><span style="color: #000000;">digit</span><span style="color: #0000FF;">+</span><span style="color: #000000;">carry</span><span style="color: #0000FF;">*</span><span style="color: #000000;">base</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><-</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">carry</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">carry</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- should have set bNegate above...</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">adt</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">a</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">adt</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"."</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bNegate</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">a</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">b_mul</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">base</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">zdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'0'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">dpa</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">dpb</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'.'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ndp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dpa</span> <span style="color: #008080;">then</span> <span style="color: #000000;">ndp</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">dpa</span><span style="color: #0000FF;">;</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dpa</span><span style="color: #0000FF;">..</span><span style="color: #000000;">dpa</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">dpb</span> <span style="color: #008080;">then</span> <span style="color: #000000;">ndp</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">dpb</span><span style="color: #0000FF;">;</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">dpb</span><span style="color: #0000FF;">..</span><span style="color: #000000;">dpb</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"0"</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">zdx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- balanced number systems</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">neg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">m</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #000000;">neg</span><span style="color: #0000FF;">:</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">),</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">+=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">:-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'0'</span>
<span style="color: #000000;">neg</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'0'</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">else</span>
<span style="color: #000080;font-style:italic;">-- non-balanced (normal) number systems</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">negative</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$];</span> <span style="color: #000000;">negative</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">'-'</span> <span style="color: #008080;">then</span> <span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$];</span> <span style="color: #000000;">negative</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">not</span> <span style="color: #000000;">negative</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">zdx</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">'0'</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">negative</span> <span style="color: #008080;">then</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">negate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ndp</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[-</span><span style="color: #000000;">ndp</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">ndp</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"."</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_trim</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">-- [note 1] not surprisingly, the decimal output is somewhat cleaner/shorter when
-- the decimal string inputs for a and c are used, whereas tests 1/2/5/7
-- (the 3-based ones) look much better with all ternary string inputs.</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--string a = b2b("523.2391403749428",decimal,alphabet), -- [see note 1]</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b2b</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"+-0++0+.+-0++0+"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">balancedternary</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b2b</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"-436.436"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">decimal</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000080;font-style:italic;">-- b = b2b("-++-0--.--0+-00+++-",balancedternary,alphabet),
-- c = b2b("65.26748971193416",decimal,alphabet), -- [see note 1]</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b2b</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"+-++-.+-++-"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">balancedternary</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">name</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'='</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">name</span><span style="color: #0000FF;">))})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" a = %.16g %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">b2dec</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">a</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" b = %.16g %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">b2dec</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">b</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" c = %.16g %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">b2dec</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">c</span><span style="color: #0000FF;">})</span>
<span style="color: #000080;font-style:italic;">-- printf(1," d = %.16g %s\n",{b2dec(d,alphabet),d})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"a*(b-c) = %.16g %s\n\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">b2dec</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">alphabet</span><span style="color: #0000FF;">),</span><span style="color: #000000;">r</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"balanced ternary"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">balancedternary</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"balanced base 27"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">balanced_base27</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"decimal"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">decimal</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"binary"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">binary</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"ternary"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ternary</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"hexadecimal"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hexadecimal</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"septemvigesimal"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">septemvigesimal</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
The printed decimal output is inherently limited to IEEE 754 precision, hence I deliberately limited output (%.16g)
because it is silly to try and go any higher, whereas the output from b_mul() is actually perfectly accurate,
see [note 1] regarding decimal/ternary input, just above.
{{out}}
<pre>
Line 767 ⟶ 1,620:
=== multiplication table ===
Without e notation, with hexadecimal across, septemvigesimal down, and balanced ternary contents!
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>printf(1,"* |")
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"* |"</span><span style="color: #0000FF;">)</span>
for j=1 to 12 do
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
printf(1," #%s %3s |",{atm2b(j,hexadecimal),atm2b(j,balancedternary)})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" #%s %3s |"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">atm2b</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hexadecimal</span><span style="color: #0000FF;">),</span><span style="color: #000000;">atm2b</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">,</span><span style="color: #000000;">balancedternary</span><span style="color: #0000FF;">)})</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=1 to 27 do
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">27</span> <span style="color: #008080;">do</span>
string a = atm2b(i,balancedternary)
<span style="color: #004080;">string</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">atm2b</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">balancedternary</span><span style="color: #0000FF;">)</span>
printf(1,"\n%-2s|",{atm2b(i,septemvigesimal)})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n%-2s|"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">atm2b</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">septemvigesimal</span><span style="color: #0000FF;">)})</span>
for j=1 to 12 do
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
if j>i then
<span style="color: #008080;">if</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">></span><span style="color: #000000;">i</span> <span style="color: #008080;">then</span>
printf(1," |")
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" |"</span><span style="color: #0000FF;">)</span>
else
<span string b style="color: atm2b(j,balancedternary)#008080;">else</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">atm2b</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">,</span><span style="color: #000000;">balancedternary</span><span style="color: #0000FF;">)</span>
string m = b_mul(a,b,balancedternary)
<span style="color: #004080;">string</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">balancedternary</span><span style="color: #0000FF;">)</span>
printf(1," %6s |",{m})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" %6s |"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">m</span><span style="color: #0000FF;">})</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
printf(1,"\n")</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
* | #1 + | #2 +- | #3 +0 | #4 ++ | #5 +-- | #6 +-0 | #7 +-+ | #8 +0- | #9 +00 | #A +0+ | #B ++- | #C ++0 |
1 | + | | | | | | | | | | | |
2 | +- | ++ | | | | | | | | | | |
3 | +0 | +-0 | +00 | | | | | | | | | |
4 | ++ | +0- | ++0 | +--+ | | | | | | | | |
5 | +-- | +0+ | +--0 | +-+- | +0-+ | | | | | | | |
6 | +-0 | ++0 | +-00 | +0-0 | +0+0 | ++00 | | | | | | |
7 | +-+ | +--- | +-+0 | +00+ | ++0- | +---0 | +--++ | | | | | |
8 | +0- | +--+ | +0-0 | ++-- | ++++ | +--+0 | +-0+- | +-+0+ | | | | |
9 | +00 | +-00 | +000 | ++00 | +--00 | +-000 | +-+00 | +0-00 | +0000 | | | |
A | +0+ | +-+- | +0+0 | ++++ | +-0-- | +-+-0 | +0--+ | +000- | +0+00 | ++-0+ | | |
B | ++- | +-++ | ++-0 | +--0- | +-00+ | +-++0 | +00-- | +0+-+ | ++-00 | ++0+- | +++++ | |
C | ++0 | +0-0 | ++00 | +--+0 | +-+-0 | +0-00 | +00+0 | ++--0 | ++000 | ++++0 | +--0-0 | +--+00 |
D | +++ | +00- | +++0 | +-0-+ | +-++- | +00-0 | +0+0+ | ++0-- | +++00 | +---++ | +--+0- | +-0-+0 |
E | +--- | +00+ | +---0 | +-0+- | +0--+ | +00+0 | ++-0- | ++0++ | +---00 | +--+-- | +-0-0+ | +-0+-0 |
F | +--0 | +0+0 | +--00 | +-+-0 | +0-+0 | +0+00 | ++0-0 | ++++0 | +--000 | +-0--0 | +-00+0 | +-+-00 |
G | +--+ | ++-- | +--+0 | +-+0+ | +000- | ++--0 | ++0++ | +---+- | +--+00 | +-00-+ | +-+--- | +-+0+0 |
H | +-0- | ++-+ | +-0-0 | +0--- | +00++ | ++-+0 | ++++- | +--00+ | +-0-00 | +-0+0- | +-+0-+ | +0---0 |
I | +-00 | ++00 | +-000 | +0-00 | +0+00 | ++000 | +---00 | +--+00 | +-0000 | +-+-00 | +-++00 | +0-000 |
J | +-0+ | +++- | +-0+0 | +0-++ | ++--- | +++-0 | +--0-+ | +-0-0- | +-0+00 | +-+00+ | +0--+- | +0-++0 |
K | +-+- | ++++ | +-+-0 | +000- | ++-0+ | ++++0 | +--+-- | +-00-+ | +-+-00 | +-+++- | +0-0++ | +000-0 |
L | +-+0 | +---0 | +-+00 | +00+0 | ++0-0 | +---00 | +--++0 | +-0+-0 | +-+000 | +0--+0 | +00--0 | +00+00 |
M | +-++ | +--0- | +-++0 | +0+-+ | ++0+- | +--0-0 | +-0-0+ | +-+--- | +-++00 | +0-0++ | +0000- | +0+-+0 |
N | +0-- | +--0+ | +0--0 | +0++- | +++-+ | +--0+0 | +-000- | +-+-++ | +0--00 | +00--- | +00+0+ | +0++-0 |
O | +0-0 | +--+0 | +0-00 | ++--0 | ++++0 | +--+00 | +-0+-0 | +-+0+0 | +0-000 | +000-0 | +0+-+0 | ++--00 |
P | +0-+ | +-0-- | +0-+0 | ++-0+ | +---0- | +-0--0 | +-0+++ | +-+++- | +0-+00 | +00+-+ | +0++-- | ++-0+0 |
Q | +00- | +-0-+ | +00-0 | ++0-- | +---++ | +-0-+0 | +-+-+- | +0--0+ | +00-00 | +0+-0- | ++---+ | ++0--0 |
10| +000 | +-000 | +0000 | ++000 | +--000 | +-0000 | +-+000 | +0-000 | +00000 | +0+000 | ++-000 | ++0000 |
</pre>
 
=={{header|Wren}}==
{{trans|Phix}}
{{libheader|Wren-str}}
{{libheader|Wren-iterate}}
{{libheader|Wren-fmt}}
Translated via the Go entry.
<syntaxhighlight lang="wren">import "./str" for Str
import "./iterate" for Stepped
import "./fmt" for Fmt
 
var maxdp = 81
var binary = "01"
var ternary = "012"
var balancedTernary = "-0+"
var decimal = "0123456789"
var hexadecimal = "0123456789ABCDEF"
var septemVigesimal = "0123456789ABCDEFGHIJKLMNOPQ"
var balancedBase27 = "ZYXWVUTSRQPON0ABCDEFGHIJKLM"
var base37 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
// converts Phix indices to Wren
var wIndex = Fn.new { |pIndex, le|
if (pIndex < 0) return pIndex + le
return pIndex - 1
}
 
var getCarry = Fn.new { |digit, base|
if (digit > base) {
return 1
} else if (digit < 1) {
return -1
}
return 0
}
 
// convert string 'b' to a decimal floating point number
var b2dec = Fn.new { |b, alphabet|
var res = 0
var base = alphabet.count
var zdx = alphabet.indexOf("0") + 1
var signed = zdx == 1 && b[0] == "-"
if (signed) b = b[1..-1]
var le = b.count
var ndp = b.indexOf(".") + 1
if (ndp != 0) {
b = Str.delete(b, ndp - 1) // remove decimal point
ndp = le - ndp
}
for (i in Stepped.ascend(1..b.count)) {
var idx = alphabet.indexOf(b[i-1]) + 1
res = base * res + idx - zdx
}
if (ndp != 0) res = res / base.pow(ndp)
if (signed) res = -res
return res
}
 
// string 'b' can be balanced or unbalanced
var negate = Fn.new { |b, alphabet|
if (alphabet[0] == "0") {
if (b != "0") b = (b[0] == "-") ? b[1..-1] : Str.insert(b, 0, "-")
} else {
for (i in Stepped.ascend(1..b.count)) {
if (b[i-1] != ".") {
var idx = alphabet.indexOf(b[i-1]) + 1
var wi = wIndex.call(-idx, alphabet.count)
b = Str.change(b, i-1, alphabet[wi])
}
}
}
return b
}
 
var bTrim = Fn.new { |b|
// trim trailing ".000"
var idx = b.indexOf(".") + 1
if (idx != 0) b = b.trimEnd("0").trimEnd(".")
// trim leading zeros but not "0.nnn"
while (b.count > 1 && b[0] == "0" && b[1] != ".") b = b[1..-1]
return b
}
 
// for balanced number systems only
var bCarry = Fn.new { |digit, base, idx, n, alphabet|
var carry = getCarry.call(digit, base)
if (carry != 0) {
for (i in Stepped.descend(idx..1)) {
if (n[i-1] != ".") {
var k = alphabet.indexOf(n[i-1]) + 1
if (k < base) {
n = Str.change(n, i-1, alphabet[k])
break
}
n = Str.change(n, i-1, alphabet[0])
}
}
digit = digit - base * carry
}
return [digit, n]
}
 
// convert a string from alphabet to alphabet2
var b2b // recursive function
b2b = Fn.new { |n, alphabet, alphabet2|
var res = "0"
var m = ""
if (n != "0") {
var base = alphabet.count
var base2 = alphabet2.count
var zdx = alphabet.indexOf("0") + 1
var zdx2 = alphabet2.indexOf("0") + 1
var carry = 0
var q = 0
var r = 0
var digit = 0
var idx = alphabet.indexOf(n[0]) + 1
var negative = (zdx == 1 && n[0] == "-") || (zdx != 1 && idx < zdx)
if (negative) n = negate.call(n, alphabet)
var ndp = n.indexOf(".") + 1
if (ndp != 0) {
var t = n
n = n[0...ndp-1]
m = t[ndp..-1]
}
res = ""
while (n.count > 0) {
q = 0
for (i in Stepped.ascend(1..n.count)) {
digit = alphabet.indexOf(n[i-1]) + 1 - zdx
q = q*base + digit
r = q.abs % base2
digit = (q.abs/base2).floor + zdx
if (q < 0) digit = digit - 1
if (zdx != 1) {
var p = bCarry.call(digit, base, i-1, n, alphabet)
digit = p[0]
n = p[1]
}
n = Str.change(n, i-1, alphabet[digit-1])
q = r
}
r = r + zdx2
if (zdx2 != 1) {
r = r + carry
carry = getCarry.call(r, base2)
r = r - base2 * carry
}
res = Str.insert(res, 0, alphabet2[r-1])
n = n.trimStart("0")
}
if (carry != 0) res = Str.insert(res, 0, alphabet2[carry+zdx2-1])
if (m.count > 0) {
res = res + "."
ndp = 0
if (zdx != 1) {
var lm = m.count
var alphaNew = base37[0...alphabet.count]
m = b2b.call(m, alphabet, alphaNew)
m = ("0" * (lm-m.count)) + m
alphabet = alphaNew
zdx = 1
}
while (m.count > 0 && ndp < maxdp) {
q = 0
for (i in Stepped.descend(m.count..1)) {
digit = alphabet.indexOf(m[i-1]) + 1 - zdx
q = q + digit * base2
r = q.abs % base + zdx
q = (q / base).truncate
if (q < 0) q = q - 1
m = Str.change(m, i-1, alphabet[r-1])
}
digit = q + zdx2
if (zdx2 != 1) {
var p = bCarry.call(digit, base2, res.count, res, alphabet2)
digit = p[0]
res = p[1]
}
res = res + alphabet2[digit-1]
m = m.trimEnd("0")
ndp = ndp + 1
}
}
res = bTrim.call(res)
if (negative) res = negate.call(res, alphabet2)
}
return res
}
 
// convert 'd' to a string in the specified base
var float2b = Fn.new { |d, alphabet|
var base = alphabet.count
var zdx = alphabet.indexOf("0") + 1
var carry = 0
var neg = d < 0
if (neg) d = -d
var res = ""
var whole = d.floor
d = d - whole
while (true) {
var ch = whole % base + zdx
if (zdx != 1) {
ch = ch + carry
carry = getCarry.call(ch, base)
ch = ch - base * carry
}
res = Str.insert(res, 0, alphabet[ch-1])
whole = (whole / base).truncate
if (whole == 0) break
}
if (carry != 0) {
res = Str.insert(res, 0, alphabet[carry+zdx-1])
carry = 0
}
if (d != 0) {
res = res + "."
var ndp = 0
while (d != 0 && ndp < maxdp) {
d = d * base
var digit = d.truncate + zdx
d = d - digit
if (zdx != 1) {
var p = bCarry.call(digit, base, res.count, res, alphabet)
digit = p[0]
res = p[1]
}
res = res + alphabet[digit-1]
ndp = ndp + 1
}
}
if (neg) res = negate.call(res, alphabet)
return res
}
 
var bSub // forwward declaration
 
var bAdd = Fn.new { |a, b, alphabet|
var base = alphabet.count
var zdx = alphabet.indexOf("0") + 1
var carry = 0
var da = 0
var db = 0
var digit = 0
if (zdx == 1) {
if (a[0] == "-") {
return bSub.call(b, negate.call(a, alphabet), alphabet)
}
if (b[0] == "-") {
return bSub.call(a, negate.call(b, alphabet), alphabet)
}
}
var adt = a.indexOf(".") + 1
var bdt = b.indexOf(".") + 1
if (adt != 0 || bdt != 0) {
if (adt != 0) {
adt = a.count - adt + 1
var wi = wIndex.call(-adt, a.count)
a = Str.delete(a, wi)
}
if (bdt != 0) {
bdt = b.count - bdt + 1
var wi = wIndex.call(-bdt, b.count)
b = Str.delete(b, wi)
}
if (bdt > adt) {
a = a + ("0" * (bdt-adt))
adt = bdt
} else if (adt > bdt) {
b = b + ("0" * (adt-bdt))
}
}
if (a.count < b.count) {
var t = a
a = b
b = t
}
for (i in Stepped.descend(-1..-a.count)) {
if (i < -a.count) {
da = 0
} else {
da = alphabet.indexOf(a[a.count + i]) + 1 - zdx
}
if (i < -b.count) {
db = 0
} else {
db = alphabet.indexOf(b[b.count + i]) + 1 - zdx
}
digit = da + db + carry + zdx
carry = getCarry.call(digit, base)
a = Str.change(a, i + a.count, alphabet[digit-carry*base-1])
if (i < -b.count && carry == 0) break
}
if (carry != 0) {
a = Str.insert(a, 0, alphabet[carry+zdx-1])
}
if (adt != 0) {
var wi = wIndex.call(-adt+1, a.count)
a = Str.insert(a, wi, ".")
}
a = bTrim.call(a)
return a
}
 
var aSmaller = Fn.new { |a, b, alphabet|
if (a.count != b.count) Fiber.abort("strings should be equal in length")
for (i in Stepped.ascend(1..a.count)) {
var da = alphabet.indexOf(a[i-1]) + 1
var db = alphabet.indexof(b[i-1]) + 1
if (da != db) return da < db
}
return false
}
 
// declared earlier
bSub = Fn.new { |a, b, alphabet|
var base = alphabet.count
var zdx = alphabet.indexOf("0") + 1
var carry = 0
var da = 0
var db = 0
var digit = 0
if (zdx == 1) {
if (a[0] == "-") {
return negate.call(bAdd.call(negate.call(a, alphabet), b, alphabet), alphabet)
}
if (b[0] == "-") {
return bAdd.call(a, negate.call(b, alphabet), alphabet)
}
}
var adt = a.indexOf(".") + 1
var bdt = b.indexOf(".") + 1
if (adt != 0 || bdt != 0) {
if (adt != 0) {
adt = a.count - adt + 1
var wi = wIndex.call(-adt, a.count)
a = Str.delete(a, wi)
}
if (bdt != 0) {
bdt = b.count - bdt + 1
var wi = wIndex.call(-bdt, b.count)
b = Str.delete(b, wi)
}
if (bdt > adt) {
a = a + ("0" * (bdt-adt))
adt = bdt
} else if (adt > bdt) {
b = b + ("0" * (adt-bdt))
}
}
var bNegate = false
if (a.count < b.count || (a.count == b.count && aSmaller.call(a, b, alphabet))) {
bNegate = true
var t = a
a = b
b = t
}
for (i in Stepped.descend(-1..-a.count)) {
if (i < -a.count) {
da = 0
} else {
da = alphabet.indexOf(a[a.count+i]) + 1 - zdx
}
if (i < -b.count) {
db = 0
} else {
db = alphabet.indexOf(b[b.count+i]) + 1 - zdx
}
digit = da - db - carry + zdx
carry = 0
if (digit <= 0) carry = 1
a = Str.change(a, i+a.count, alphabet[digit+carry*base-1])
if (i < -b.count && carry == 0) break
}
if (carry != 0) Fiber.abort("carry should be zero")
if (adt != 0) {
var wi = wIndex.call(-adt+1, a.count)
a = Str.insert(a, wi, ".")
}
a = bTrim.call(a)
if (bNegate) a = negate.call(a, alphabet)
return a
}
 
var bMul = Fn.new { |a, b, alphabet|
var zdx = alphabet.indexOf("0") + 1
var dpa = a.indexOf(".") + 1
var dpb = b.indexOf(".") + 1
var ndp = 0
if (dpa != 0) {
ndp = ndp + a.count - dpa
a = Str.delete(a, dpa-1)
}
if (dpb != 0) {
ndp = ndp + b.count - dpb
b = Str.delete(b, dpb-1)
}
var pos = a
var res = "0"
if (zdx != 1) {
// balanced number systems
var neg = negate.call(pos, alphabet)
for (i in Stepped.descend(b.count..1)) {
var m = alphabet.indexOf(b[i-1]) + 1 - zdx
while (m != 0) {
var temp = pos
var temp2 = -1
if (m < 0) {
temp = neg
temp2 = 1
}
res = bAdd.call(res, temp, alphabet)
m = m + temp2
}
pos = pos + "0"
neg = neg + "0"
}
} else {
// non-balanced number systems
var negative = false
if (a[0] == "-") {
a = a[1..-1]
negative = true
}
if (b[0] == "-") {
b = b[1..-1]
negative = !negative
}
for (i in Stepped.descend(b.count..1)) {
var m = alphabet.indexOf(b[i-1]) + 1 - zdx
while (m > 0) {
res = bAdd.call(res, pos, alphabet)
m = m - 1
}
pos = pos + "0"
}
if (negative) res = negate.call(res, alphabet)
}
if (ndp != 0) {
var wi = wIndex.call(-ndp, res.count)
res = Str.insert(res, wi, ".")
}
res = bTrim.call(res)
return res
}
 
var multTable = Fn.new {
System.print("multiplication table")
System.print("====================")
System.write("* |")
for (j in 1..12) {
Fmt.write(" #$s $3s |", float2b.call(j, hexadecimal), float2b.call(j, balancedTernary))
}
for (i in 1..27) {
var a = float2b.call(i, balancedTernary)
Fmt.write("\n$-2s|", float2b.call(i, septemVigesimal))
for (j in 1..12) {
if (j > i) {
System.write(" |")
} else {
var b = float2b.call(j, balancedTernary)
var m = bMul.call(a, b, balancedTernary)
Fmt.write(" $6s |", m)
}
}
}
System.print()
}
 
var test = Fn.new {|name, alphabet|
var a = b2b.call("+-0++0+.+-0++0+", balancedTernary, alphabet)
var b = b2b.call("-436.436", decimal, alphabet)
var c = b2b.call("+-++-.+-++-", balancedTernary, alphabet)
var d = bSub.call(b, c, alphabet)
var r = bMul.call(a, d, alphabet)
Fmt.print("$s\n$s", name, "=" * name.count)
Fmt.print(" a = $.14f $s", b2dec.call(a, alphabet), a)
Fmt.print(" b = $.14f $s", b2dec.call(b, alphabet), b)
Fmt.print(" c = $.14f $s", b2dec.call(c, alphabet), c)
Fmt.print("a*(b-c) = $.14f $s\n", b2dec.call(r, alphabet), r)
}
 
test.call("balanced ternary", balancedTernary)
test.call("balanced base 27", balancedBase27)
test.call("decimal", decimal)
test.call("binary", binary)
test.call("ternary", ternary)
test.call("hexadecimal", hexadecimal)
test.call("septemvigesimal", septemVigesimal)
multTable.call()</syntaxhighlight>
 
{{out}}
<pre>
balanced ternary
================
a = 523.23914037494285 +-0++0+.+-0++0+
b = -436.43599999999992 -++-0--.--0+-00+++-0-+---0-+0++++0--0000+00-+-+--+0-0-00--++0-+00---+0+-+++0+-0----0++
c = 65.26748971193416 +-++-.+-++-
a*(b-c) = -262510.90267998125637 ----000-0+0+.0+0-0-00---00--0-0+--+--00-0++-000++0-000-+0+-----+++-+-0+-+0+0++0+0-++-++0+---00++++
 
balanced base 27
================
a = 523.23914037494285 AUJ.FLI
b = -436.43600000000004 NKQ.YFDFTYSMHVANGXPVXHIZJRJWZD0PBGFJAEBAKOZODLY0ITEHPQLSQSGLFZUINATKCIKUVMWEWJMQ0COTS
c = 65.26748971193416 BK.GF
a*(b-c) = -262510.90267998125637 ZVPJ.CWNYQPEENDVDPNJZXKFGCLHKLCX0YIBOMETHFWWBTVUFAH0SEZMTBJDCRRAQIQCAWMKXSTPYUXYPK0LODUO
 
decimal
=======
a = 523.23914037494296 523.239140374942844078646547782350251486053955189757658893461362597165066300868770004
b = -436.43599999999998 -436.436
c = 65.26748971193415 65.267489711934156378600823045267489711934156378600823045267489711934156378600823045
a*(b-c) = -262510.90267998137278 -262510.90267998140903693918986303277315826215892262734715612833785876513103053772667101895163734826631742752252837097627017862754285047634638652268078676654605120794218
 
binary
======
a = 523.23914037494274 1000001011.001111010011100001001101101110011000100001011110100101001010100100000111001000111
b = -436.43600000000004 -110110100.011011111001110110110010001011010000111001010110000001000001100010010011011101001
c = 65.26748971193416 1000001.01000100011110100011010010101100110001100000111010111111101111001001001101111101
a*(b-c) = -262510.90267998143099 -1000000000101101110.111001110001011000001001000001101110011111011100000100000100001000101011100011110010110001010100110111001011101001010000001110110100111110001101000000001111110101
 
ternary
=======
a = 523.23914037494285 201101.0201101
b = -436.43600000000021 -121011.102202211210021110012111201022222000202102010100101200200110122011122101110212
c = 65.26748971193416 2102.02102
a*(b-c) = -262510.90267998125637 -111100002121.2201010011100110022102110002120222120100001221111011202022012121122001201122110221112
 
hexadecimal
===========
a = 523.23914037494274 20B.3D384DB9885E94A90723EF9CBCB174B443E45FFC41152FE0293416F15E3AC303A0F3799ED81589C62
b = -436.43599999999998 -1B4.6F9DB22D0E5604189374BC6A7EF9DB22D0E5604189374BC6A7EF9DB22D0E5604189374BC6A7EF9DB2
c = 65.26748971193416 41.447A34ACC60EBFBC937D5DC2E5A99CF8A021B641511E8D2B3183AFEF24DF5770B96A673E28086D905
a*(b-c) = -262510.90267998143099 -4016E.E7160906E7DC10422DA508321819F4A637E5AEE668ED5163B12FCB17A732442F589975B7F24112B2E8F6E95EAD45803915EE26D20DF323D67CAEEC75D7BED68AA34E02F2B492257D66F028545FB398F60E
 
septemvigesimal
===============
a = 523.23914037494285 JA.6C9
b = -436.43600000000004 -G4.BKML7C5DJ8Q0KB39AIICH4HACN02OJKGPLOPG2D1MFBQI6LJ33F645JELD7I0Q6FNHG88E9M9GE3QO276
c = 65.26748971193416 2B.76
a*(b-c) = -262510.90267998125637 -D92G.OA1C42LM0N8N30HDAFKJNEIFEOB0BHP1DM6ILA9P797KPJ05MCE6OGMO54Q3I3NQ9DGB673C8BC2FQF1N82
 
multiplication table
====================
* | #1 + | #2 +- | #3 +0 | #4 ++ | #5 +-- | #6 +-0 | #7 +-+ | #8 +0- | #9 +00 | #A +0+ | #B ++- | #C ++0 |
1 | + | | | | | | | | | | | |
9,482

edits