= Radix Float
Radix provides a Float class for working with rational numbers in various bases.
Actually Radix's implementation of Float is a fixed point, not a
floating point.
require 'radix'
D = Radix::DOT
== Initialization
Radix::Float's initializer can accept either an Integer, Float, String or
Array as a value and an integer base.
Give a float value, it will automatically be converted to the base
specified.
check do |float, base, digits|
r = Radix::Float.new(float, base)
r.digits.assert == digits
end
ok 8.5, 2, [1,0,0,0,D,1]
ok 4.5, 2, [ 1,0,0,D,1]
ok 8.1, 10, [ 8,D,1]
ok 10.2, 10, [1,0,D,2]
#ok 8.1, 16, [ 8,D,1]
#ok 16.1, 16, [1,0,D,1]
Give an integer value, it will automatically be converted to the base
specified and given a fraction part set to zero.
check do |float, base, digits|
r = Radix::Float.new(float, base)
r.digits.assert == digits
end
ok 8, 2, [1,0,0,0,D,0]
ok 4, 2, [ 1,0,0,D,0]
ok 8, 10, [ 8,D,0]
ok 10, 10, [1,0,D,0]
ok 8, 16, [ 8,D,0]
ok 16, 16, [1,0,D,0]
Given a float, the same will occur.
ok 8.0, 2, [1,0,0,0,D,0]
ok 4.0, 2, [ 1,0,0,D,0]
ok 8.0, 10, [ 8,D,0]
ok 10.0, 10, [1,0,D,0]
ok 8.0, 16, [ 8,D,0]
ok 16.0, 16, [1,0,D,0]
Where as a String value is taken to already be in the base given.
ok "1000", 2, [1,0,0,0,D,0]
ok "100", 2, [ 1,0,0,D,0]
ok "8", 10, [ 8,D,0]
ok "10", 10, [1,0,D,0]
ok "8", 16, [ 8,D,0]
ok "10", 16, [1,0,D,0]
ok "1000.0", 2, [1,0,0,0,D,0]
ok "100.0", 2, [ 1,0,0,D,0]
ok "8.0", 10, [ 8,D,0]
ok "10.0", 10, [1,0,D,0]
ok "8.0", 16, [ 8,D,0]
ok "10.0", 16, [1,0,D,0]
And an Array is also taken to be in the base given.
ok %w[1 0 0 0], 2, [1,0,0,0,D,0]
ok %w[ 1 0 0], 2, [ 1,0,0,D,0]
ok %w[ 8], 10, [ 8,D,0]
ok %w[1 0], 10, [1,0,D,0]
ok %w[ 8], 16, [ 8,D,0]
ok %w[1 0], 16, [1,0,D,0]
Passing in an Array with a fraction part, either the DOT constant can be used,
which is simply the symbol :'.', or the string '.' can be used.
ok %w[1 0 0 0 . 0], 2, [1,0,0,0,D,0]
ok %w[ 1 0 0 . 0], 2, [ 1,0,0,D,0]
ok %w[ 8 . 0], 10, [ 8,D,0]
ok %w[1 0 . 0], 10, [1,0,D,0]
ok %w[ 8 . 0], 16, [ 8,D,0]
ok %w[1 0 . 0], 16, [1,0,D,0]
Integers can also be negative, rather than positive. In each case
just prepend the value with a minus sign.
check do |float, base, digits|
r = Radix::Float.new(float, base)
r.digits.assert = digits
r.assert.negative?
end
ok( -8, 2, ['-',1,0,0,0,D,0])
ok( "-1000", 2, ['-',1,0,0,0,D,0])
ok( %w[- 1 0 0 0], 2, ['-',1,0,0,0,D,0])
If a value has a digit outside of the range of the base an ArgumentError
will be raised.
expect ArgumentError do
Radix::Float.new('9', 2)
end
Radix provides a convenience extension method to Integer, String and Array
called #b, to more easily initialize a Radix numeric object. The method simply
passes the receiver on to `Radix::Integer#new`.
check do |float, base, digits|
r = float.b(base)
r.assert.is_a?(Radix::Float)
r.digits.assert = digits
end
ok 8.0, 2, [1,0,0,0,D,0]
ok 4.0, 2, [ 1,0,0,D,0]
ok "1000.0", 2, [1,0,0,0,D,0]
ok "100.0", 2, [ 1,0,0,D,0]
ok %w"1 0 0 0 . 0", 2, [1,0,0,0,D,0]
ok %w"1 0 0 . 0", 2, [ 1,0,0,D,0]
== Conversion
Radix integers can ve converted to other bases with the #convert method.
b = "1000.0".b(2)
d = b.convert(10)
d.digits.assert == [8,D,0]
We can convert a Radix::Float to a regular base-10 Float with the #to_f
method.
b = "1000.0".b(2)
d = b.to_f
d.assert == 8.0
We can convert a Radix::Float to a regular base-10 Integer with the #to_i
method.
b = "1000.0".b(2)
d = b.to_i
d.assert == 8
=== Equality
Radix extend the Integer, String and Array classes with the #b method
which simplifies the creation of Radix::Float instances. The following
return the equivalent instance of Radix::Float.
a = 8.0.b(2)
b = "1000.0".b(2)
c = [1,0,0,0,'.',0].b(2)
a.assert = b
b.assert = c
c.assert = a
a.assert = 8.0
b.assert = 8.0
c.assert = 8.0
More stringent equality can be had from #eql?, in which the other integer
must be a Radix::Integer too.
a.assert.eql?(b)
a.refute.eql?(8.0)
== Operations
Radix::Float supports all the usual mathematical operators.
=== Addition
check do |a, b, x|
(a + b).assert = x
end
ok "1000.0".b(2), "0010.0".b(2), "1010.0".b(2)
ok "1000.0".b(2), "2.0".b(8), "1010.0".b(2)
ok "1000.0".b(2), "2.0".b(8), "10.0".b(10)
A more complex example.
x = "AZ42.0".b(62) + "54.0".b(10)
x.assert == "2518124.0".b(10)
x.assert == 2518124.0
Adding negative integers will, of course, be akin to subtraction.
ok "1000.0".b(2), "-0010".b(2), "110.0".b(2)
ok "1000.0".b(2), "-2".b(8), "110.0".b(2)
ok "1000.0".b(2), "-2".b(8), "6.0".b(10)
ok "-1000.0".b(2), "0010".b(2), "-110.0".b(2)
ok "-1000.0".b(2), "2".b(8), "-110.0".b(2)
ok "-1000.0".b(2), "2".b(8), "-6.0".b(10)
ok "-1000.0".b(2), "-0010".b(2), "-1010.0".b(2)
ok "-1000.0".b(2), "-2".b(8), "-1010.0".b(2)
ok "-1000.0".b(2), "-2".b(8), "-10.0".b(10)
=== Subtraction
check do |a, b, x|
(a - b).assert == x
end
ok "1000.0".b(2), "10".b(2), "110.0".b(2)
ok "1000.0".b(2), "2".b(8), "110.0".b(2)
ok "1000.0".b(2), "2".b(8), "6.0".b(8)
ok "1000.0".b(2), "2".b(8), "6.0".b(10)
A more complex example.
x = "AZ42.0".b(62) - "54".b(10)
x.assert == "2518016.0".b(10)
x.assert == 2518016.0
=== Multiplication
check do |a, b, x|
(a * b).assert = x
end
ok "1000.0".b(2), "10".b(2), "10000.0".b(2)
ok "1000.0".b(2), "2".b(8), "10000.0".b(2)
ok "1000.0".b(2), "2".b(8), "20.0".b(8)
ok "1000.0".b(2), "2".b(8), "16.0".b(10)
A more complex example.
x = "Z42.0".b(62) * "4.0".b(10)
x.assert == "539160.0".b(10)
x.assert == 539160.0
=== Division
check do |a, b, x|
(a / b).assert = x
end
ok "1000.0".b(2), "10".b(2), "100.0".b(2)
ok "1000.0".b(2), "2".b(8), "100.0".b(2)
ok "1000.0".b(2), "2".b(8), "4.0".b(8)
ok "1000.0".b(2), "2".b(8), "4.0".b(10)
A more complex example.
x = "AZ40.0".b(62) / "62.0".b(10)
x.assert == "40614.0".b(10)
x.assert == 40614.0
=== Power
check do |a, b, x|
(a ** b).assert == x
end
ok "1000.0".b(2), "10.0".b(2), 64.0
=== Modulo
check do |a, b, x|
(a % b).assert == x
end
ok "1000.0".b(2), "10".b(2), 0
ok "1000.0".b(2), "11".b(2), 2
== Coerce
When a Radix::Integer is the operand in an operation against a regular
Ruby Integer, the calculation should still work via #coerce.
check do |a, b, x|
(a + b).assert == x
end
ok 10.0, "10".b(2), "12".b(10)