radix 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,294 @@
1
+ = Radix Float
2
+
3
+ Radix provides a Float class for working with rational numbers in various bases.
4
+ Actually Radix's implementation of Float is a <i>fixed point</i>, not a
5
+ <i>floating point</i>.
6
+
7
+ require 'radix'
8
+
9
+ D = Radix::DOT
10
+
11
+ == Initialization
12
+
13
+ Radix::Float's initializer can accept either an Integer, Float, String or
14
+ Array as a value and an integer base.
15
+
16
+ Give a float value, it will automatically be converted to the base
17
+ specified.
18
+
19
+ check do |float, base, digits|
20
+ r = Radix::Float.new(float, base)
21
+ r.digits.assert == digits
22
+ end
23
+
24
+ ok 8.5, 2, [1,0,0,0,D,1]
25
+ ok 4.5, 2, [ 1,0,0,D,1]
26
+
27
+ ok 8.1, 10, [ 8,D,1]
28
+ ok 10.2, 10, [1,0,D,2]
29
+ #ok 8.1, 16, [ 8,D,1]
30
+ #ok 16.1, 16, [1,0,D,1]
31
+
32
+ Give an integer value, it will automatically be converted to the base
33
+ specified and given a fraction part set to zero.
34
+
35
+ check do |float, base, digits|
36
+ r = Radix::Float.new(float, base)
37
+ r.digits.assert == digits
38
+ end
39
+
40
+ ok 8, 2, [1,0,0,0,D,0]
41
+ ok 4, 2, [ 1,0,0,D,0]
42
+
43
+ ok 8, 10, [ 8,D,0]
44
+ ok 10, 10, [1,0,D,0]
45
+ ok 8, 16, [ 8,D,0]
46
+ ok 16, 16, [1,0,D,0]
47
+
48
+ Given a float, the same will occur.
49
+
50
+ ok 8.0, 2, [1,0,0,0,D,0]
51
+ ok 4.0, 2, [ 1,0,0,D,0]
52
+
53
+ ok 8.0, 10, [ 8,D,0]
54
+ ok 10.0, 10, [1,0,D,0]
55
+ ok 8.0, 16, [ 8,D,0]
56
+ ok 16.0, 16, [1,0,D,0]
57
+
58
+ Where as a String value is taken to already be in the base given.
59
+
60
+ ok "1000", 2, [1,0,0,0,D,0]
61
+ ok "100", 2, [ 1,0,0,D,0]
62
+
63
+ ok "8", 10, [ 8,D,0]
64
+ ok "10", 10, [1,0,D,0]
65
+ ok "8", 16, [ 8,D,0]
66
+ ok "10", 16, [1,0,D,0]
67
+
68
+ ok "1000.0", 2, [1,0,0,0,D,0]
69
+ ok "100.0", 2, [ 1,0,0,D,0]
70
+
71
+ ok "8.0", 10, [ 8,D,0]
72
+ ok "10.0", 10, [1,0,D,0]
73
+ ok "8.0", 16, [ 8,D,0]
74
+ ok "10.0", 16, [1,0,D,0]
75
+
76
+ And an Array is also taken to be in the base given.
77
+
78
+ ok %w[1 0 0 0], 2, [1,0,0,0,D,0]
79
+ ok %w[ 1 0 0], 2, [ 1,0,0,D,0]
80
+
81
+ ok %w[ 8], 10, [ 8,D,0]
82
+ ok %w[1 0], 10, [1,0,D,0]
83
+ ok %w[ 8], 16, [ 8,D,0]
84
+ ok %w[1 0], 16, [1,0,D,0]
85
+
86
+ Passing in an Array with a fraction part, either the DOT constant can be used,
87
+ which is simply the symbol :'.', or the string '.' can be used.
88
+
89
+ ok %w[1 0 0 0 . 0], 2, [1,0,0,0,D,0]
90
+ ok %w[ 1 0 0 . 0], 2, [ 1,0,0,D,0]
91
+
92
+ ok %w[ 8 . 0], 10, [ 8,D,0]
93
+ ok %w[1 0 . 0], 10, [1,0,D,0]
94
+ ok %w[ 8 . 0], 16, [ 8,D,0]
95
+ ok %w[1 0 . 0], 16, [1,0,D,0]
96
+
97
+ Integers can also be negative, rather than positive. In each case
98
+ just prepend the value with a minus sign.
99
+
100
+ check do |float, base, digits|
101
+ r = Radix::Float.new(float, base)
102
+ r.digits.assert = digits
103
+ r.assert.negative?
104
+ end
105
+
106
+ ok( -8, 2, ['-',1,0,0,0,D,0])
107
+ ok( "-1000", 2, ['-',1,0,0,0,D,0])
108
+ ok( %w[- 1 0 0 0], 2, ['-',1,0,0,0,D,0])
109
+
110
+ If a value has a digit outside of the range of the base an ArgumentError
111
+ will be raised.
112
+
113
+ expect ArgumentError do
114
+ Radix::Float.new('9', 2)
115
+ end
116
+
117
+ Radix provides a convenience extension method to Integer, String and Array
118
+ called #b, to more easily initialize a Radix numeric object. The method simply
119
+ passes the receiver on to `Radix::Integer#new`.
120
+
121
+ check do |float, base, digits|
122
+ r = float.b(base)
123
+ r.assert.is_a?(Radix::Float)
124
+ r.digits.assert = digits
125
+ end
126
+
127
+ ok 8.0, 2, [1,0,0,0,D,0]
128
+ ok 4.0, 2, [ 1,0,0,D,0]
129
+
130
+ ok "1000.0", 2, [1,0,0,0,D,0]
131
+ ok "100.0", 2, [ 1,0,0,D,0]
132
+
133
+ ok %w"1 0 0 0 . 0", 2, [1,0,0,0,D,0]
134
+ ok %w"1 0 0 . 0", 2, [ 1,0,0,D,0]
135
+
136
+ == Conversion
137
+
138
+ Radix integers can ve converted to other bases with the #convert method.
139
+
140
+ b = "1000.0".b(2)
141
+ d = b.convert(10)
142
+ d.digits.assert == [8,D,0]
143
+
144
+ We can convert a Radix::Float to a regular base-10 Float with the #to_f
145
+ method.
146
+
147
+ b = "1000.0".b(2)
148
+ d = b.to_f
149
+ d.assert == 8.0
150
+
151
+ We can convert a Radix::Float to a regular base-10 Integer with the #to_i
152
+ method.
153
+
154
+ b = "1000.0".b(2)
155
+ d = b.to_i
156
+ d.assert == 8
157
+
158
+ === Equality
159
+
160
+ Radix extend the Integer, String and Array classes with the #b method
161
+ which simplifies the creation of Radix::Float instances. The following
162
+ return the equivalent instance of Radix::Float.
163
+
164
+ a = 8.0.b(2)
165
+ b = "1000.0".b(2)
166
+ c = [1,0,0,0,'.',0].b(2)
167
+
168
+ a.assert = b
169
+ b.assert = c
170
+ c.assert = a
171
+
172
+ a.assert = 8.0
173
+ b.assert = 8.0
174
+ c.assert = 8.0
175
+
176
+ More stringent equality can be had from #eql?, in which the other integer
177
+ must be a Radix::Integer too.
178
+
179
+ a.assert.eql?(b)
180
+ a.refute.eql?(8.0)
181
+
182
+ == Operations
183
+
184
+ Radix::Float supports all the usual mathematical operators.
185
+
186
+ === Addition
187
+
188
+ check do |a, b, x|
189
+ (a + b).assert = x
190
+ end
191
+
192
+ ok "1000.0".b(2), "0010.0".b(2), "1010.0".b(2)
193
+ ok "1000.0".b(2), "2.0".b(8), "1010.0".b(2)
194
+ ok "1000.0".b(2), "2.0".b(8), "10.0".b(10)
195
+
196
+ A more complex example.
197
+
198
+ x = "AZ42.0".b(62) + "54.0".b(10)
199
+ x.assert == "2518124.0".b(10)
200
+ x.assert == 2518124.0
201
+
202
+ Adding negative integers will, of course, be akin to subtraction.
203
+
204
+ ok "1000.0".b(2), "-0010".b(2), "110.0".b(2)
205
+ ok "1000.0".b(2), "-2".b(8), "110.0".b(2)
206
+ ok "1000.0".b(2), "-2".b(8), "6.0".b(10)
207
+
208
+ ok "-1000.0".b(2), "0010".b(2), "-110.0".b(2)
209
+ ok "-1000.0".b(2), "2".b(8), "-110.0".b(2)
210
+ ok "-1000.0".b(2), "2".b(8), "-6.0".b(10)
211
+
212
+ ok "-1000.0".b(2), "-0010".b(2), "-1010.0".b(2)
213
+ ok "-1000.0".b(2), "-2".b(8), "-1010.0".b(2)
214
+ ok "-1000.0".b(2), "-2".b(8), "-10.0".b(10)
215
+
216
+ === Subtraction
217
+
218
+ check do |a, b, x|
219
+ (a - b).assert == x
220
+ end
221
+
222
+ ok "1000.0".b(2), "10".b(2), "110.0".b(2)
223
+ ok "1000.0".b(2), "2".b(8), "110.0".b(2)
224
+ ok "1000.0".b(2), "2".b(8), "6.0".b(8)
225
+ ok "1000.0".b(2), "2".b(8), "6.0".b(10)
226
+
227
+ A more complex example.
228
+
229
+ x = "AZ42.0".b(62) - "54".b(10)
230
+ x.assert == "2518016.0".b(10)
231
+ x.assert == 2518016.0
232
+
233
+ === Multiplication
234
+
235
+ check do |a, b, x|
236
+ (a * b).assert = x
237
+ end
238
+
239
+ ok "1000.0".b(2), "10".b(2), "10000.0".b(2)
240
+ ok "1000.0".b(2), "2".b(8), "10000.0".b(2)
241
+ ok "1000.0".b(2), "2".b(8), "20.0".b(8)
242
+ ok "1000.0".b(2), "2".b(8), "16.0".b(10)
243
+
244
+ A more complex example.
245
+
246
+ x = "Z42.0".b(62) * "4.0".b(10)
247
+ x.assert == "539160.0".b(10)
248
+ x.assert == 539160.0
249
+
250
+ === Division
251
+
252
+ check do |a, b, x|
253
+ (a / b).assert = x
254
+ end
255
+
256
+ ok "1000.0".b(2), "10".b(2), "100.0".b(2)
257
+ ok "1000.0".b(2), "2".b(8), "100.0".b(2)
258
+ ok "1000.0".b(2), "2".b(8), "4.0".b(8)
259
+ ok "1000.0".b(2), "2".b(8), "4.0".b(10)
260
+
261
+ A more complex example.
262
+
263
+ x = "AZ40.0".b(62) / "62.0".b(10)
264
+ x.assert == "40614.0".b(10)
265
+ x.assert == 40614.0
266
+
267
+ === Power
268
+
269
+ check do |a, b, x|
270
+ (a ** b).assert == x
271
+ end
272
+
273
+ ok "1000.0".b(2), "10.0".b(2), 64.0
274
+
275
+ === Modulo
276
+
277
+ check do |a, b, x|
278
+ (a % b).assert == x
279
+ end
280
+
281
+ ok "1000.0".b(2), "10".b(2), 0
282
+ ok "1000.0".b(2), "11".b(2), 2
283
+
284
+ == Coerce
285
+
286
+ When a Radix::Integer is the operand in an operation against a regular
287
+ Ruby Integer, the calculation should still work via #coerce.
288
+
289
+ check do |a, b, x|
290
+ (a + b).assert == x
291
+ end
292
+
293
+ ok 10.0, "10".b(2), "12".b(10)
294
+
@@ -0,0 +1,84 @@
1
+ = Radix Rational
2
+
3
+ require 'radix'
4
+
5
+ == Initialization
6
+
7
+ Radix::Rational's initializer takes a numerator and a denominator,
8
+ either of which can be an Integer, Float, String or Array along witha
9
+ an integer base.
10
+
11
+ Give a integer value, it will automatically be converted to the base
12
+ specified.
13
+
14
+ check do |num, dem, base, eqf|
15
+ r = Radix::Rational.new(num, dem, base)
16
+ r.assert == eqf
17
+ end
18
+
19
+ ok 1, 2, 2, 0.5
20
+ ok 1, 1, 2, 1.0
21
+
22
+ ok 8, 1, 10, 8.0
23
+ ok 8, 5, 10, 1.6
24
+ ok 8, 8, 10, 1.0
25
+
26
+ ok 10, 1, 10, 10.0
27
+ ok 10, 2, 10, 5.0
28
+ ok 10, 5, 10, 2.0
29
+
30
+ ok 8, 1, 16, 8.0
31
+ ok 16, 1, 16, 16.0
32
+
33
+ == Reduction
34
+
35
+ check do |a, x|
36
+ r = a.reduce
37
+ r.assert == x
38
+ end
39
+
40
+ ok [10,5].br(10), [2,1].br(10)
41
+ ok [30,3].br(10), [10,1].br(10)
42
+
43
+ == Operations
44
+
45
+ === Addition
46
+
47
+ check do |a, b, x|
48
+ r = a + b
49
+ r.assert == x
50
+ end
51
+
52
+ ok [8,5].br(10), [1,2].br(10), [21,10].br(10)
53
+
54
+ ok [8,5].br(10), 1, [13,5].br(10)
55
+
56
+ ok [8,5].br(10), 0.5, [21,10].br(10)
57
+
58
+ === Subtraction
59
+
60
+ check do |a, b, x|
61
+ r = a - b
62
+ r.assert == x
63
+ end
64
+
65
+ ok [8,5].br(10), [1,2].br(10), [11,10].br(10)
66
+
67
+ === Multiplication
68
+
69
+ check do |a, b, x|
70
+ r = a * b
71
+ r.assert == x
72
+ end
73
+
74
+ ok [8,5].br(10), [1,2].br(10), [8,10].br(10)
75
+
76
+ === Division
77
+
78
+ check do |a, b, x|
79
+ r = a / b
80
+ r.assert == x
81
+ end
82
+
83
+ ok [8,5].br(10), [1,2].br(10), [16,5].br(10)
84
+
@@ -0,0 +1,78 @@
1
+ = Radix::Base
2
+
3
+ The Radix::Base class is an encapsulatin of a numeric base. By creating
4
+ an instance of Base one can convert numbers to and from other bases.
5
+
6
+ require 'radix/base'
7
+
8
+ == Base Instance
9
+
10
+ First let's try something we all know, converting decimal to hexideciaml.
11
+ To do this we setup the radix base objects for each base.
12
+
13
+ b10 = Radix::Base.new(Radix::BASE::B10)
14
+ b16 = Radix::Base.new(Radix::BASE::B16)
15
+
16
+ Now we can covert from one base to the other.
17
+
18
+ b16.convert("16" , b10).should == "10"
19
+ b16.convert("160", b10).should == "A0"
20
+ b16.convert("255", b10).should == "FF"
21
+
22
+ To confirm, lets convert from hexidecimal back to decimal.
23
+
24
+ b10.convert("10", b16).should == "16"
25
+ b10.convert("A0", b16).should == "160"
26
+ b10.convert("FF", b16).should == "255"
27
+
28
+ If we are happy with standard encodings then we can simply provide an
29
+ integer base, rather than a Radix::Base object.
30
+
31
+ b10.convert("10", 16).should == "16"
32
+ b10.convert("A0", 16).should == "160"
33
+ b10.convert("FF", 16).should == "255"
34
+
35
+ Now let's try a more down to earth base, my favorite,
36
+ senary, or base six.
37
+
38
+ b6 = Radix::Base.new(0..5)
39
+ b6.convert("39", 10).should == "103"
40
+
41
+ And the notations need not be in ASCII order. Odd alternate notations
42
+ can be used as well.
43
+
44
+ b10 = Radix::Base.new([:Q, :W, :E, :R, :T, :Y, :U, :I, :O, :U])
45
+ b10.convert("FF", 16) #=> "EYY"
46
+
47
+ == Encoding and Decoding
48
+
49
+ Radix::Base instances can also be used to encode and decode strings.
50
+
51
+ b16.encode("CHARLIE").should == "434841524C4945"
52
+ b16.decode("434841524C4945").should == "CHARLIE"
53
+
54
+ == Module Methods
55
+
56
+ For further convenience, Radix::base provides functions to convert to and from
57
+ standard notations upto 62 without creating an instance of Radix::Base.
58
+
59
+ Radix.convert("10", 16, 10).should == "16"
60
+ Radix.convert("A0", 16, 10).should == "160"
61
+ Radix.convert("FF", 16, 10).should == "255"
62
+
63
+ Let's try that again with the maximum base supported.
64
+
65
+ Radix.convert( "62", 10, 62).should == "10"
66
+ Radix.convert("8814542", 10, 62).should == "az42"
67
+
68
+ Radix.convert( "10", 62, 10).should == "62"
69
+ Radix.convert( "az42", 62, 10).should == "8814542"
70
+
71
+ Finally, we will demonstrate how to convert bases larger than 62.
72
+ These can only be represented as arrays since there are not enough
73
+ latin characters to represent them.
74
+
75
+ Radix.convert_base([100, 10], 256, 10).should == [2, 5, 6, 1, 0]
76
+ Radix.convert_base([2, 5, 6, 1, 0], 10, 256).should == [100, 10]
77
+ Radix.convert_base([1, 0, 1, 0, 1], 2, 10).should == [2, 1]
78
+