Generalised floating point addition: Difference between revisions

No edit summary
Line 729:
 
=={{header|Phix}}==
{{incomplete|Phix}}
See [[Generalised_floating_point_multiplication#Phix]] - Obviously I either completely missed or more likely deliberately ignored the requirement for handling numbers other than decimal. The b_add() [and b_sub()] mentioned on the multiplication task are probably not all that difficult.
===bigatom===
Note this is decimal-only, and that mpfr.e does not really cope because it cannot hold decimal fractions exactly (though it could probably be fudged with a smidgen of rounding)
<lang Phix>include bigatom.e
{} = ba_scale(200)
Line 756 ⟶ 755:
</pre>
 
===bcd/string arithmeticany base ===
Uses b_add() and b_mul() from [[Generalised_floating_point_multiplication#Phix]]
May yet form the basis of something useful in builtins. (same output)
<lang Phix>function-- bcd_normalise(string a)demo\rosetta\Generic_addition.exw
function bcd_addnormalise_decimal(string a,b)
--
-- 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")
Line 778 ⟶ 777:
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[1z..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 digite_notation(integerstring d1, d2, carrya)
-- eg "12.341000000" ==> "12","341e6"
-- common code
if not find('.',resa) then ?9/0 end if -- (to do)
integer digit = d1+d2-'0'+carry
carryinteger l = digit>'9'length(a)
afa = trim_tail(afa,'".0'")
if carry then digit -= 10 end if
returnl {digit,carry}-= length(a)
elsifif dl!=0 then
end function
a &=sprintf("e%d",l)
 
end if
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
Line 832 ⟶ 803:
integer e = 63
for n = -7 to 21 do
string bd = normalise_decimal(sprintf("%se%d",{s,e})),
e1 = normalise_decimal(sprintf("1e%d",e)),
res = b_add(b_mul(bd,"81",decimal),e1,decimal)
printf(1,"%2d res : %s\n",{n,e_notation(res)})
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>
same ouput
 
=={{header|Racket}}==
7,804

edits