Imaginary base numbers: Difference between revisions

Content added Content deleted
m (→‎{{header|Perl 6}}: slight efficiency tweak)
(Added Sidef)
Line 382: Line 382:
5+5i.&base(-6i) = 5.U : '5.U'.&parse-base(-6i) = 5+5i
5+5i.&base(-6i) = 5.U : '5.U'.&parse-base(-6i) = 5+5i
227.65625+10.859375i.&base( 4i) = 10234.5678 : '10234.5678'.&parse-base( 4i) = 227.65625+10.859375i</pre>
227.65625+10.859375i.&base( 4i) = 10234.5678 : '10234.5678'.&parse-base( 4i) = 227.65625+10.859375i</pre>

=={{header|Sidef}}==
{{trans|Perl 6}}
<lang ruby>func base (Number num, Number radix { _ ~~ (-36 .. -2) }, precision = -15) -> String {
num || return '0'

var place = 0
var result = ''
var value = num
var upper_bound = 1/(-radix + 1)
var lower_bound = radix*upper_bound

while (!(lower_bound <= value) || !(value < upper_bound)) {
value = num/(radix**++place)
}

while ((value || (place > 0)) && (place > precision)) {
var digit = (radix*value - lower_bound -> int)
value = (radix*value - digit)
result += '.' if (!place && !result.contains('.'))
result += ((digit == -radix) ? (digit-1 -> base(-radix) + '0') : digit.base(-radix))
place--
}

return result
}

func base (Number num, Number radix { .re == 0 }, precision = -8) -> String {

(radix.im.abs ~~ 2..6) || die "Base #{radix} out of range"

var (re, im) = (num.re, num.im)
var (re_wh, re_fr='') = base(re, -radix.im**2, precision).split('.')...
var (im_wh, im_fr='') = base(im/radix.im, -radix.im**2, precision).split('.')...

func zip (String a, String b) {
var l = ('0' * abs(a.len - b.len))
chars(a+l) ~Z chars(b+l) -> flat.join.sub(/0+\z/, '') || '0'
}

var whole = zip(re_wh.flip, im_wh.flip).flip
var fraction = zip(im_fr, re_fr)
fraction == '0' ? whole : "#{whole}.#{fraction}"
}

func parse_base (String str, Number radix { .re == 0 }) -> Number {

if (str.char(0) == '-') {
return (-1 * parse_base(str.substr(1), radix))
}

var (whole, frac='') = str.split('.')...

var fraction = frac.chars.map_kv {|k,v|
Number(v, radix.im**2) * radix**-(k+1)
}.sum

fraction += whole.flip.chars.map_kv {|k,v|
Number(v, radix.im**2) * radix**k
}.sum

return fraction
}

var tests = [0, 2i, 1, 2i, 5, 2i, -13, 2i, 9i, 2i, -3i, 2i, 7.75-7.5i, 2i, .25, 2i, # base 2i tests
5+5i, 2i, 5+5i, 3i, 5+5i, 4i, 5+5i, 5i, 5+5i, 6i, # same value, positive imaginary bases
5+5i, -2i, 5+5i, -3i, 5+5i, -4i, 5+5i, -5i, 5+5i, -6i, # same value, negative imaginary bases
227.65625+10.859375i, 4i] # larger test value

tests.each_slice(2, {|v,r|
var ibase = base(v, r)
printf("base(%20s, %2si) = %-10s : parse_base(%12s, %2si) = %s\n",
v, r.im, ibase, "'#{ibase}'", r.im, parse_base(ibase, r).round(-8))
})</lang>
{{out}}
<pre>
base( 0, 2i) = 0 : parse_base( '0', 2i) = 0
base( 1, 2i) = 1 : parse_base( '1', 2i) = 1
base( 5, 2i) = 10301 : parse_base( '10301', 2i) = 5
base( -13, 2i) = 1030003 : parse_base( '1030003', 2i) = -13
base( 9i, 2i) = 103010.2 : parse_base( '103010.2', 2i) = 9i
base( -3i, 2i) = 1030.2 : parse_base( '1030.2', 2i) = -3i
base( 7.75-7.5i, 2i) = 11210.31 : parse_base( '11210.31', 2i) = 7.75-7.5i
base( 0.25, 2i) = 1.03 : parse_base( '1.03', 2i) = 0.25
base( 5+5i, 2i) = 10331.2 : parse_base( '10331.2', 2i) = 5+5i
base( 5+5i, 3i) = 25.3 : parse_base( '25.3', 3i) = 5+5i
base( 5+5i, 4i) = 25.c : parse_base( '25.c', 4i) = 5+5i
base( 5+5i, 5i) = 15 : parse_base( '15', 5i) = 5+5i
base( 5+5i, 6i) = 15.6 : parse_base( '15.6', 6i) = 5+5i
base( 5+5i, -2i) = 11321.2 : parse_base( '11321.2', -2i) = 5+5i
base( 5+5i, -3i) = 1085.6 : parse_base( '1085.6', -3i) = 5+5i
base( 5+5i, -4i) = 10f5.4 : parse_base( '10f5.4', -4i) = 5+5i
base( 5+5i, -5i) = 10o5 : parse_base( '10o5', -5i) = 5+5i
base( 5+5i, -6i) = 5.u : parse_base( '5.u', -6i) = 5+5i
base(227.65625+10.859375i, 4i) = 10234.5678 : parse_base('10234.5678', 4i) = 227.65625+10.859375i
</pre>