Generalised floating point addition: Difference between revisions

(Added Go)
Line 715:
21 : 1.000000e+72
</pre>
 
=={{header|Phix}}==
===bigatom===
<lang Phix>include bigatom.e
{} = ba_scale(200)
 
string s = "12345679",
t = "123456790"
integer e = 63
for n = -7 to 21 do
bigatom bd = ba_new(sprintf("%se%d",{s,e})),
e1 = ba_new(sprintf("1e%d",e)),
res = ba_add(ba_mul(bd,81),e1)
printf(1,"%2d : %s\n",{n,ba_sprintf("%.eB",res)})
s = t & s
e -= 9
end for</lang>
{{out|Output (trimmed)}}
<pre>
-7 : 1e72
...
21 : 1e72
</pre>
===bcd/string arithmetic===
May yet form the basis of something useful in builtins. (same output)
<lang Phix>function bcd_normalise(string a)
--
-- eg "12.34e-3" == "0.01234" ==> "0","01234"
-- and/or "1e2" ==> "100",""
--
integer d = find('.',a),
e = find('e',a)
string f = ""
if e then
integer {{z}} = scanf(a[e+1..$],"%d")
a = a[1..e-1]
if d then
-- eg 12.34e-3 == 1234e-5
a[d..d] = ""
z -= length(a)-d+1
end if
if z>=0 then
-- eg 1e2 ==> 100
a &= repeat('0',z)
elsif z<-length(a) then
-- eg 1234e-5 == 0.01234 ==> "0","01234"
{a,f} = {"0",repeat('0',-z-length(a))&a}
else
-- eg 1234e-3 == 1.234 ==> "1","234"
{a,f} = {a[1..z-1],a[z..$]}
end if
elsif d then
-- eg "12.34" ==> "12","34"
{a,f} = {a[1..d-1],a[d+1..$]}
end if
return {a,f}
end function
 
function digit(integer d1, d2, carry)
-- common code
integer digit = d1+d2-'0'+carry
carry = digit>'9'
if carry then digit -= 10 end if
return {digit,carry}
end function
 
function bcd_add(string a,b)
string af,bf -- fractional parts
{a,af} = bcd_normalise(a)
{b,bf} = bcd_normalise(b)
if length(b)>length(a) then {a,b} = {b,a} end if
if length(bf)>length(af) then {af,bf} = {bf,af} end if
integer carry = 0
-- 1) add shorter fraction, eg .1234 + .01 ==> .1334 carry 0
-- (ie we don't touch the "34", and the '.' is implicit)
for i=length(bf) to 1 by -1 do
{af[i],carry} = digit(af[i],bf[i],carry)
end for
af = trim_tail(af,'0')
-- 2) add shorter integer, eg (9)909 + 101 ==> (9)010 carry 1
-- (these -ve indexes are simply going from right to left)
for i=-1 to -length(b) by -1 do
{a[i],carry} = digit(a[i],b[i],carry)
end for
-- 3) propagate carry into the longer integer if possible
for i=-length(b)-1 to -length(a) by -1 do
if carry=0 then exit end if
{a[i],carry} = digit(a[i],'0',carry)
end for
-- 4) otherwise prepend it (cannot be >1)
if carry then a = "1"&a end if
if length(af) then a &= "."&af end if
return a
end function
 
string s = "12345679",
t = "123456790"
integer e = 63
for n = -7 to 21 do
string bd = sprintf("%se%d",{s,e}),
e1 = sprintf("1e%d",e),
res = bd
for i=1 to 4 do
res = bcd_add(bcd_add(res,res),res)
end for
res = bcd_add(res,e1)
if not find('.',res) then
string z = trim_tail(res,'0')
if z!=res then
res = sprintf("%se%d",{z,length(res)-length(z)})
end if
end if
printf(1,"%2d : %s\n",{n,res})
s = t & s
e -= 9
end for</lang>
 
=={{header|Racket}}==
7,805

edits