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)) })