Imaginary base numbers: Difference between revisions
Content added Content deleted
(Added C#) |
|||
Line 1,385: | Line 1,385: | ||
227.65625+10.859375i.&base( 4i) = 10234.5678 : '10234.5678'.&parse-base( 4i) = 227.65625+10.859375i |
227.65625+10.859375i.&base( 4i) = 10234.5678 : '10234.5678'.&parse-base( 4i) = 227.65625+10.859375i |
||
31433.3487654321-2902.4480452675i.&base( 6i) = PERL6.ROCKS : 'PERL6.ROCKS'.&parse-base( 6i) = 31433.3487654321-2902.4480452675i</pre> |
31433.3487654321-2902.4480452675i.&base( 6i) = PERL6.ROCKS : 'PERL6.ROCKS'.&parse-base( 6i) = 31433.3487654321-2902.4480452675i</pre> |
||
=={{header|Phix}}== |
|||
{{trans|Sidef}} |
|||
<lang Phix>include complex.e |
|||
function base2(atom num, integer radix, precision = -8) |
|||
if radix<-36 or radix>-2 then throw("radix out of range (-2..-36)") end if |
|||
sequence result |
|||
if num=0 then |
|||
result = {"0",""} |
|||
else |
|||
integer place = 0 |
|||
result = "" |
|||
atom v = num |
|||
atom upper_bound = 1/(1-radix), |
|||
lower_bound = radix*upper_bound |
|||
while not(lower_bound <= v) or not(v < upper_bound) do |
|||
place += 1 |
|||
v = num/power(radix,place) |
|||
end while |
|||
while (v or place > 0) and (place > precision) do |
|||
integer digit = floor(radix*v - lower_bound) |
|||
v = (radix*v - digit) |
|||
if place=0 and not find('.',result) then result &= '.' end if |
|||
result &= digit+iff(digit>9?'a'-10:'0') |
|||
place -= 1 |
|||
end while |
|||
integer dot = find('.',result) |
|||
if dot then |
|||
result = trim_tail(result,'0') |
|||
result = {result[1..dot-1],result[dot+1..$]} |
|||
else |
|||
result = {result,""} |
|||
end if |
|||
end if |
|||
return result |
|||
end function |
|||
function zip(string a, string b) |
|||
integer ld = length(a)-length(b) |
|||
if ld!=0 then |
|||
if ld>0 then |
|||
b &= repeat('0',ld) |
|||
else |
|||
a &= repeat('0',abs(ld)) |
|||
end if |
|||
end if |
|||
string res = "" |
|||
for i=1 to length(a) do |
|||
res &= a[i]&b[i] |
|||
end for |
|||
res = trim_tail(res,'0') |
|||
if res="" then res = "0" end if |
|||
return res |
|||
end function |
|||
function base(complexn num, integer radix, precision = -8) |
|||
integer absrad = abs(radix), |
|||
radix2 = -power(radix,2) |
|||
if absrad<2 or absrad>6 then throw("base radix out of range") end if |
|||
atom {re, im} = {complex_real(num), complex_imag(num)} |
|||
string {re_wh, re_fr} = base2(re, radix2, precision), |
|||
{im_wh, im_fr} = base2(im/radix, radix2, precision) |
|||
string whole = reverse(zip(reverse(re_wh), reverse(im_wh))), |
|||
fraction = zip(im_fr, re_fr) |
|||
if fraction!="0" then whole &= '.'&fraction end if |
|||
return whole |
|||
end function |
|||
function parse_base(string str, integer radix) |
|||
complexn fraction = 0 |
|||
integer dot = find('.',str) |
|||
if dot then |
|||
string fr = str[dot+1..$] |
|||
for i=1 to length(fr) do |
|||
integer c = fr[i] |
|||
c -= iff(c>='a'?'a'-10:'0') |
|||
fraction = complex_add(fraction,complex_mul(c,complex_power({0,radix},-i))) |
|||
end for |
|||
str = str[1..dot-1] |
|||
end if |
|||
str = reverse(str) |
|||
for i=1 to length(str) do |
|||
integer c = str[i] |
|||
c -= iff(c>='a'?'a'-10:'0') |
|||
fraction = complex_add(fraction,complex_mul(c,complex_power({0,radix},(i-1)))) |
|||
end for |
|||
return fraction |
|||
end function |
|||
constant tests = {{0,2},{1,2},{5,2},{-13,2},{{0,9},2},{{0,-3},2},{{7.75,-7.5}, 2},{.25, 2}, -- base 2i tests |
|||
{{5,5}, 2},{{5,5}, 3},{{5,5}, 4},{{5,5}, 5},{{5,5}, 6}, -- same value, positive imaginary bases |
|||
{{5,5},-2},{{5,5},-3},{{5,5},-4},{{5,5},-5},{{5,5},-6}, -- same value, positive imaginary bases |
|||
{{227.65625,10.859375},4}, -- larger test value |
|||
{{-579.8225308641975744,-5296.406378600824},6}} -- phix.rules |
|||
-- matches output of Sidef and Perl6: |
|||
for t=1 to length(tests) do |
|||
{complexn v, integer r} = tests[t] |
|||
string ibase = base(v,r), |
|||
strv = complex_sprint(v), |
|||
strb = complex_sprint(parse_base(ibase, r)) |
|||
printf(1,"base(%20s, %2di) = %-10s : parse_base(%12s, %2di) = %s\n", |
|||
{strv, r, ibase, '"'&ibase&'"', r, strb}) |
|||
end for |
|||
-- matches output of Kotlin, Java, Go, D, and C#: |
|||
for ri=1 to 2 do -- real then imag |
|||
for i=1 to 16 do |
|||
complexn c = iff(ri=1?i:{0,i}), |
|||
nc = complex_neg(c) |
|||
string sc = complex_sprint(c), |
|||
snc = complex_sprint(nc), |
|||
ib = base(c,2), |
|||
inb = base(nc,2), |
|||
rc = complex_sprint(parse_base(ib,2)), |
|||
rnc = complex_sprint(parse_base(inb,2)) |
|||
printf(1,"%4s -> %8s -> %4s %4s -> %8s -> %4s\n", |
|||
{sc, ib, rc, snc, inb, rnc }) |
|||
end for |
|||
puts(1,"\n") |
|||
end for</lang> |
|||
{{out}} |
|||
Matches the output of Sidef and Perl6, except for the final line: |
|||
<pre> |
|||
base( -579.823-5296.41i, 6i) = phix.rules : parse_base("phix.rules", 6i) = -579.823-5296.41i |
|||
</pre> |
|||
Also matches the output of Kotlin, Java, Go, D, and C#, except the even entries in the second half, eg: |
|||
<pre> |
|||
2i -> 10 -> 2i -2i -> 1030 -> -2i |
|||
</pre> |
|||
instead of |
|||
<pre> |
|||
2i -> 10.0 -> 2i -2i -> 1030.0 -> -2i |
|||
</pre> |
|||
ie the unnecessary trailing ".0" are trimmed. (see talk page) |
|||
=={{header|Sidef}}== |
=={{header|Sidef}}== |