Generalised floating point multiplication: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(20 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.
 
import (
Deviation from task description:
"fmt"
b_add() only copes with negative parameters when using balanced number bases, hence I
"log"
changed the test slightly to remove the signs, or you could just omit the b-c part of
"math"
the test by setting b to -501.7034897119342 (ie -436.436 - 65.26748971193418) and then
"strings"
do a*b rather than a*(b-c), or you could fix b_add() and/or write a brand new b_sub().
)
<lang Phix>-- demo\rosetta\Generic_multiplication.exw
constant MAX_DP = 81
 
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]='-')
ifndp negative then:= strings.IndexByte(n, = n[2.'.$]') end+ if1
integerif ndp != find('.',n)0 {
if ndp! n, m = n[0:ndp-1], thenn[ndp:]
}
{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
 
functionfunc b_addbAdd(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{
-- (let me know if youa[0] can== fix this for'-' me!){
if a[1]='-' or b[1]='-' thenreturn ?9/0bSub(b, end if --negate(a, +vealphabet), onlyalphabet)
end if }
integer adt if b[0] == find('.-',a), {
bdtreturn = findbSub('.'a, negate(b, alphabet), alphabet)
if adt or bdt then}
}
-- remove the '.'s and zero-pad the shorter as needed
adt := strings.IndexByte(a, '.') + 1
-- (thereafter treat them as two whole integers)
bdt := strings.IndexByte(b, '.') + 1
-- eg "1.23"+"4.5" -> "123"+"450" (leaving adt==2)
if adt then adt != length(a)-adt+1;0 || a[-adt..-adt]bdt != ""0 end if{
if bdt then bdtadt != length(b)-bdt+1; b[-bdt..-bdt] = "" end0 if{
if bdt> adt then= len(a) - adt + 1
agi &:= repeatgIndex('0',bdt-adt, len(a))
a = removeByte(a, gi)
}
if bdt != 0 {
bdt = len(b) - 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}
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 b_mulaSmaller(string a, b, alphabet string) bool {
integerif baselen(a) != lengthlen(alphabetb), {
log.Fatal("strings should be equal zdxin = find('0',alphabetlength"),
}
dpa = find('.',a),
for i := 1; i dpb <= findlen('.',ba),; i++ {
da := strings.IndexByte(alphabet, a[i-1]) ndp =+ 01
if dpa then ndp +db := lengthstrings.IndexByte(a)-dpa;alphabet, ab[dpa..dpai-1]) = "" end+ if1
if dpb then ndp +=if length(b)-dpb; b[dpb..dpb]da != ""db end if{
string pos = a, res = "0" return da < db
if zdx!=1 then }
}
-- balanced number systems
return false
string neg = negate(pos,alphabet)
}
for i=length(b) to 1 by -1 do
 
integer m = find(b[i],alphabet)-zdx
func bSub(a, b, alphabet string) string {
while m do
base res := b_addlen(res,iff(m<0?neg:pos),alphabet)
zdx := strings.IndexByte(alphabet, '0') + 1
m += iff(m<0?+1:-1)
var carry, da, db, digit end whileint
if zdx == 1 pos &= '0'{
if a[0] neg &== '0-' {
return negate(bAdd(negate(a, alphabet), b, alphabet), alphabet)
end for
else }
--if non-balancedb[0] (normal)== number'-' systems{
return bAdd(a, negate(b, alphabet), alphabet)
bool negative = false
}
if a[1]='-' then a = a[2..$]; negative = true end if
}
if b[1]='-' then b = b[2..$]; negative = not negative end if
adt := strings.Index(a, ".") + 1
for i=length(b) to 1 by -1 do
bdt := strings.Index(b, ".") + 1
integer m = find(b[i],alphabet)-zdx
if adt != 0 || bdt != while m>0 do{
if adt != 0 res = b_add(res,pos,alphabet){
adt = len(a) - madt -=+ 1
endgi while:= gIndex(-adt, len(a))
posa &= '0'removeByte(a, gi)
end for}
if negative then resbdt != negate(res,alphabet) end0 if{
bdt = len(b) - bdt + 1
end if
gi := gIndex(-bdt, len(b))
if ndp then
res[-ndp..-ndp-1] b = "."removeByte(b, gi)
end if }
res = b_trim(res) if bdt > adt {
a += strings.Repeat("0", bdt-adt)
adt = bdt
} else if adt > bdt {
b += strings.Repeat("0", adt-bdt)
}
}
bNegate := false
if len(a) < len(b) || (len(a) == len(b) && aSmaller(a, b, alphabet)) {
bNegate = true
a, b = b, a
}
for i := -1; i >= -len(a); i-- {
if i < -len(a) {
da = 0
} 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 = 0
if digit <= 0 {
carry = 1
}
a = changeByte(a, i+len(a), alphabet[digit+carry*base-1])
if i < -len(b) && carry == 0 {
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
}
 
func bMul(a, b, alphabet string) string {
zdx := strings.IndexByte(alphabet, '0') + 1
dpa := strings.IndexByte(a, '.') + 1
dpb := strings.IndexByte(b, '.') + 1
ndp := 0
if dpa != 0 {
ndp += len(a) - dpa
a = removeByte(a, dpa-1)
}
if dpb != 0 {
ndp += len(b) - dpb
b = removeByte(b, dpb-1)
}
pos, res := a, "0"
if zdx != 1 {
// balanced number systems
neg := negate(pos, alphabet)
for i := len(b); i >= 1; i-- {
m := strings.IndexByte(alphabet, b[i-1]) + 1 - zdx
for m != 0 {
temp, temp2 := pos, -1
if m < 0 {
temp = neg
temp2 = 1
}
res = bAdd(res, temp, alphabet)
m += temp2
}
pos += "0"
neg += "0"
}
} else {
// non-balanced number systems
negative := false
if a[0] == '-' {
a = a[1:]
negative = true
}
if b[0] == '-' {
b = 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)
-- [note 2] proof that b_mul() copes with negative numbers, though b_add() dis'ne.
test("binary", binary)
test("ternary", ternary)
test("hexadecimal", hexadecimal)
test("septemvigesimal", septemVigesimal)
multTable()
}</syntaxhighlight>
 
procedure test(string name, alphabet)
--string a = b2b("523.2391403749428",decimal,alphabet), -- [see note 1]
string a = b2b("+-0++0+.+-0++0+",balancedternary,alphabet),
b = b2b("436.436",decimal,alphabet),
-- b = b2b("+--+0++.++0-+00---+",balancedternary,alphabet),
-- b = b2b("-501.7034897119342",decimal,alphabet), -- [see note 2]
-- c = b2b("65.26748971193416",decimal,alphabet), -- [see note 1]
c = b2b("+-++-.+-++-",balancedternary,alphabet),
d = b_add(b,c,alphabet),
r = b_mul(a,d,alphabet)
-- r = b_mul(a,b,alphabet) -- [see note 2]
printf(1,"%s\n%s\n",{name,repeat('=',length(name))})
printf(1," a = %.16g %s\n",{b2dec(a,alphabet),a})
printf(1," b = %.16g %s\n",{b2dec(b,alphabet),b})
printf(1," c = %.16g %s\n",{b2dec(c,alphabet),c})
-- printf(1," d = %.16g %s\n",{b2dec(d,alphabet),d})
printf(1,"a*(b+c) = %.16g %s\n\n",{b2dec(r,alphabet),r})
-- printf(1," a*b = %.16g %s\n\n",{b2dec(r,alphabet),r}) -- [see note 2]
end procedure
test("balanced ternary", balancedternary)
test("balanced base 27", balanced_base27)
test("decimal", decimal)
test("binary", binary)
test("ternary", ternary)
test("hexadecimal", hexadecimal)
test("septemvigesimal", septemvigesimal)</lang>
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] above.
{{out}}
<pre>
Line 643 ⟶ 803:
================
a = 523.2391403749428 +-0++0+.+-0++0+
b = -436.4359999999999 +--+0++.++-0-+00-.--+0+-00+++0+-0-+---0++0000-00+-0+-++-0+0--0000+00-+-+--0+0-0-00--+++-0-+00---0-+0+-+++0+-0----0++
c = 65.26748971193416 +-++-.+-++-
a*(b+-c) = -262510.9026799813 ++++000+0-0-.0--000-0+0+00+++00++.0+0-++0-++00+0--+000-00--0-0+000--+-0-00-0++-000++0-000-+0+---+--+0++-+-0+-+0--+0-++0+-0-+--0+-++0+00----00++++
 
balanced base 27
================
a = 523.2391403749428 AUJ.FLI
b = -436.4359999999999 NKQ.YFDFTYSMHVANGXPVXHIZJRJWZD0PBGFJAEBAKOZODLY0ITEHPQLSQSGLFZUINATKCIKUVMWEWJMQ0COTS
b = 436.436 AXD.LSQSGLFZUINATKCIKUVMWEWJMQ0COTSWNRONXBMBQYL0VGRUCDYFDFTYSMHVANGXPVXHIZJRJWZD0PBGF
c = 65.26748971193416 BK.GF
a*(b-c) = -262510.9026799812 ZVPJ.CWNYQPEENDVDPNJZXKFGCLHKLCX0YIBOMETHFWWBTVUFAH0SEZMTBJDCRRAQIQCAWMKXSTPYUXYPK0LODUO
a*(b+c) = 262510.9026799813 MICW.PJALDCRRAQIQCAWMKXSTPYUXYPK0LVOBZRGUSJJOGIHSNU0FRMZGOWQPEENDVDPNJZXKFGCLHKLCX0YBQHB
 
decimal
=======
a = 523.2391403749428 523.239140374942844078646547782350251486053955189757658893461362597165066300868770004
b = -436.436 -436.436
c = 65.26748971193413 65.267489711934156378600823045267489711934156378600823045267489711934156378600823045
a*(b-c) = -262510.9026799813 -262510.90267998140903693918986303277315826215892262734715612833785876513103053772667101895163734826631742752252837097627017862754285047634638652268078676654605120794218
 
binary
======
a = 523.2391403749427 1000001011.001111010011100001001101101110011000100001011110100101001010100100000111001000111
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>
balanced ternary
================
a = 523.2391403749428 +-0++0+.+-0++0+
b = -436.4359999999999 -++-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.9026799813 ----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.2391403749428 AUJ.FLI
b = -436.436 NKQ.YFDFTYSMHVANGXPVXHIZJRJWZD0PBGFJAEBAKOZODLY0ITEHPQLSQSGLFZUINATKCIKUVMWEWJMQ0COTS
c = 65.26748971193416 BK.GF
a*(b-c) = -262510.9026799813 ZVPJ.CWNYQPEENDVDPNJZXKFGCLHKLCX0YIBOMETHFWWBTVUFAH0SEZMTBJDCRRAQIQCAWMKXSTPYUXYPK0LODUO
 
decimal
=======
a = 523.239140374943 523.239140374942844078646547782350251486053955189757658893461362597165066300868770004
b = -436.436 -436.436
c = 65.26748971193415 65.267489711934156378600823045267489711934156378600823045267489711934156378600823045
a*(b+-c) = -262510.9026799814 -262510.90267998140903693918986303277315826215892262734715612833785876513103053772667101895163734826631742752252837097627017862754285047634638652268078676654605120794218
 
binary
======
a = 523.2391403749427 1000001011.001111010011100001001101101110011000100001011110100101001010100100000111001000111
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.4360000000001 -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.436 -G4.BKML7C5DJ8Q0KB39AIICH4HACN02OJKGPLOPG2D1MFBQI6LJ33F645JELD7I0Q6FNHG88E9M9GE3QO276
c = 65.26748971193416 2B.76
a*(b+-c) = -262510.9026799813 -D92G.OA1C42LM0N8N30HDAFKJNEIFEOB0BHP1DM6ILA9P797KPJ05MCE6OGMO54Q3I3NQ9DGB673C8BC2FQF1N82
</pre>
 
=== 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 | + | | | | | | | | | | | |
2 | +- | ++ | | | | | | | | | | |
9,476

edits