Jump to content

Imaginary base numbers: Difference between revisions

(Added C#)
Line 1,385:
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>
 
=={{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}}==
7,818

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.