radix 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.index +7 -3
- data/.yardopts +6 -3
- data/HISTORY.md +21 -5
- data/README.md +16 -7
- data/demo/issues/004_zero_empty_string.md +18 -0
- data/lib/radix.rb +13 -40
- data/lib/radix.yml +7 -3
- data/lib/radix/base.rb +137 -20
- data/lib/radix/float.rb +206 -14
- data/lib/radix/integer.rb +221 -21
- data/lib/radix/numeric.rb +99 -26
- data/lib/radix/operator.rb +82 -0
- data/lib/radix/rational.rb +100 -27
- metadata +20 -3
data/lib/radix/numeric.rb
CHANGED
@@ -2,57 +2,90 @@ require 'radix/base'
|
|
2
2
|
|
3
3
|
module Radix
|
4
4
|
|
5
|
-
#
|
5
|
+
# Radix separator used in string and array representations.
|
6
6
|
DOT = '.'
|
7
7
|
|
8
|
-
#
|
8
|
+
# Division character for rational numbers
|
9
9
|
DIV = '/'
|
10
10
|
|
11
|
-
#
|
11
|
+
# Default seperator character.
|
12
12
|
DIVIDER = " "
|
13
13
|
|
14
|
-
|
15
|
-
#
|
14
|
+
##
|
15
|
+
# Radix::Numeric class inherits from Ruby's Numeric class. It is then
|
16
|
+
# subclassed by Radix::Integer and Radix::Float.
|
17
|
+
#
|
18
|
+
# @todo Make immutable, but best way to do it?
|
19
|
+
# @example First suggestion
|
20
|
+
# class << self
|
21
|
+
# alias_method :_new, :new
|
22
|
+
# private :_new
|
23
|
+
# end
|
24
|
+
# @example Second suggestion
|
25
|
+
# def self.new(value, base=10)
|
26
|
+
# @cache ||= {}
|
27
|
+
# @cache[[value, base]] ||= _new(value, base)
|
28
|
+
# end
|
16
29
|
class Numeric < ::Numeric
|
17
30
|
|
18
|
-
|
19
|
-
|
20
|
-
#class << self
|
21
|
-
# alias_method :_new, :new
|
22
|
-
# private :_new
|
23
|
-
#end
|
31
|
+
##
|
32
|
+
# Addition, binary operation.
|
24
33
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#end
|
29
|
-
|
30
|
-
# Addition
|
34
|
+
# @param [Radix::Numeric] other
|
35
|
+
#
|
36
|
+
# @return [Radix::Numeric] Result of arithmetic operation.
|
31
37
|
def +(other)
|
32
38
|
operation(:+, other)
|
33
39
|
end
|
34
40
|
|
35
|
-
|
41
|
+
##
|
42
|
+
# Subtraction, binary operation.
|
43
|
+
#
|
44
|
+
# @param [Radix::Numeric] other
|
45
|
+
#
|
46
|
+
# @return [Radix::Numeric] Result of arithmetic operation.
|
36
47
|
def -(other)
|
37
48
|
operation(:-, other)
|
38
49
|
end
|
39
50
|
|
40
|
-
|
51
|
+
##
|
52
|
+
# Multiplication, binary operation.
|
53
|
+
#
|
54
|
+
# @param [Radix::Numeric] other
|
55
|
+
#
|
56
|
+
# @return [Radix::Numeric] Result of arithmetic operation.
|
41
57
|
def *(other)
|
42
58
|
operation(:*, other)
|
43
59
|
end
|
44
60
|
|
45
|
-
|
61
|
+
##
|
62
|
+
# Division, binary operation.
|
63
|
+
#
|
64
|
+
# @param [Radix::Numeric] other
|
65
|
+
#
|
66
|
+
# @return [Radix::Numeric] Result of arithmetic operation.
|
46
67
|
def /(other)
|
47
68
|
operation(:/, other)
|
48
69
|
end
|
49
70
|
|
50
71
|
private
|
51
72
|
|
73
|
+
##
|
74
|
+
# Parses the value of the base and character set to use.
|
52
75
|
#
|
76
|
+
# @param [Fixnum, Array<String>] base
|
77
|
+
# The value of the base, or a set of characters to use as
|
78
|
+
# representation of the base.
|
79
|
+
#
|
80
|
+
# @note If an array of String characters is passed, its length is the
|
81
|
+
# value of the base level.
|
82
|
+
#
|
83
|
+
# @return [Array<(Fixnum, [Array<String>, nil])>] Two part array:
|
84
|
+
# 0 - Fixnum value of the base.
|
85
|
+
# 1 - Nil, or Array of characters representing the base values.
|
53
86
|
def parse_base(base)
|
54
87
|
case base
|
55
|
-
|
88
|
+
when Array
|
56
89
|
code = base
|
57
90
|
base = base.size
|
58
91
|
else
|
@@ -62,20 +95,42 @@ module Radix
|
|
62
95
|
return base, code
|
63
96
|
end
|
64
97
|
|
98
|
+
##
|
99
|
+
# Simply returns the passed value. Used for simplifying creation of
|
100
|
+
# Radix::Numeric instances.
|
101
|
+
#
|
102
|
+
# @param [Radix::Float, Radix::Integer] value Given value.
|
103
|
+
# @param [Fixnum, Array<String>] base Desired base.
|
65
104
|
#
|
105
|
+
# @return [Radix::Float, Radix::Integer] The passed value.
|
66
106
|
def parse_numeric(value, base)
|
67
107
|
value
|
68
108
|
end
|
69
109
|
|
110
|
+
##
|
70
111
|
# If a float style string is passed in for +value+, e.g. "9.5", the
|
71
112
|
# decimal will simply be truncated. So "9.x" would become "9".
|
113
|
+
#
|
114
|
+
# @param [String] value
|
115
|
+
# Given value.
|
116
|
+
#
|
117
|
+
# @param [Fixnum, Array<String>] base
|
118
|
+
# Desired base.
|
119
|
+
#
|
120
|
+
# @return [Radix::Float, Radix::Integer] The passed value.
|
72
121
|
def parse_string(value, base)
|
73
122
|
digits = value.split(//)
|
74
123
|
parse_array(digits, base)
|
75
124
|
end
|
76
125
|
|
126
|
+
##
|
77
127
|
# Take an Array in the form of [d1, d2, ..., DOT, d-1, d-2, ...]
|
78
128
|
# and convert it to base ten, and store in @value.
|
129
|
+
#
|
130
|
+
# @param [Array<String, Numeric>] value Given value.
|
131
|
+
# @param [Fixnum, Array<String>] base Desired base.
|
132
|
+
#
|
133
|
+
# @return [Fixnum] Decimal version of passed array in base context.
|
79
134
|
def parse_array(value, base)
|
80
135
|
value = value.dup
|
81
136
|
|
@@ -93,12 +148,20 @@ module Radix
|
|
93
148
|
|
94
149
|
v = decimal(value, base)
|
95
150
|
|
96
|
-
neg ? -v : v
|
151
|
+
neg ? -v : v # Returns negated v if value array.first == "-"
|
97
152
|
end
|
98
153
|
|
99
|
-
|
100
|
-
#
|
101
|
-
# is slighly different.
|
154
|
+
##
|
155
|
+
# Convert array of values of a different base to decimal. This handles
|
156
|
+
# integer values. The method for Radix::Float is slighly different.
|
157
|
+
#
|
158
|
+
# @param [Array<Numeric, String>] digits
|
159
|
+
# Representation of base values.
|
160
|
+
#
|
161
|
+
# @param [Fixnum, Array<String>] base
|
162
|
+
# The base to convert from.
|
163
|
+
#
|
164
|
+
# @return [Integer] The digits of base converted to decimal.
|
102
165
|
def decimal(digits, base)
|
103
166
|
e = digits.size - 1
|
104
167
|
v = 0
|
@@ -109,8 +172,13 @@ module Radix
|
|
109
172
|
v
|
110
173
|
end
|
111
174
|
|
175
|
+
##
|
112
176
|
# Map array of values to base encoding. If no encoding is defined
|
113
177
|
# this simply returns the +digits+ unchanged.
|
178
|
+
#
|
179
|
+
# @param [Array<String, Numeric>] digits
|
180
|
+
#
|
181
|
+
# @return [Array<String, Fixnum>] Encoded digits, or digits if @code is nil
|
114
182
|
def base_encode(digits)
|
115
183
|
return digits unless @code
|
116
184
|
digits.map do |i|
|
@@ -123,7 +191,12 @@ module Radix
|
|
123
191
|
end
|
124
192
|
end
|
125
193
|
|
126
|
-
|
194
|
+
##
|
195
|
+
# Decode an encoded array. Defaults to BASE::B62 if self.code is not set.
|
196
|
+
#
|
197
|
+
# @param [Array<String, Numeric>] digits The encoded characters.
|
198
|
+
#
|
199
|
+
# @return [Array<String, Numeric>] Decoded array.
|
127
200
|
def base_decode(digits)
|
128
201
|
#return digits unless code
|
129
202
|
code = self.code || BASE::B62
|
data/lib/radix/operator.rb
CHANGED
@@ -0,0 +1,82 @@
|
|
1
|
+
# This script defines the `#b` core extension method for Ruby's built-in
|
2
|
+
# Numeric classes to make it easy to convert to Radix base classes.
|
3
|
+
|
4
|
+
##
|
5
|
+
# Adds the b(base) method to this ruby class for quickly creating Radix
|
6
|
+
# instances.
|
7
|
+
class ::Float
|
8
|
+
|
9
|
+
##
|
10
|
+
# Takes a Ruby Float and makes it into a Radix::Float as given base.
|
11
|
+
#
|
12
|
+
# @param [Fixnum, Array<String>] base
|
13
|
+
# The desired base.
|
14
|
+
#
|
15
|
+
# @return [Radix::Float]
|
16
|
+
def b(base)
|
17
|
+
Radix::Float.new(self, base)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Adds the b(base) method to this ruby class for quickly creating Radix
|
23
|
+
# instances.
|
24
|
+
class ::Integer
|
25
|
+
|
26
|
+
##
|
27
|
+
# Takes a Ruby Integer and makes it into a Radix::Integer as given base.
|
28
|
+
#
|
29
|
+
# @param [Fixnum, Array<String>] base
|
30
|
+
# The desired base.
|
31
|
+
#
|
32
|
+
# @return [Radix::Integer]
|
33
|
+
def b(base)
|
34
|
+
Radix::Integer.new(self, base)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Adds the b(base) method to this ruby class for quickly creating Radix
|
40
|
+
# instances.
|
41
|
+
class ::String
|
42
|
+
|
43
|
+
##
|
44
|
+
# Takes a String and makes it into a Radix::Integer or Radix::Float as given
|
45
|
+
# base. Float is determined by a "." character in string instance
|
46
|
+
#
|
47
|
+
# @param [Fixnum, Array<String>] base
|
48
|
+
# The desired base.
|
49
|
+
#
|
50
|
+
# @return [Radix::Integer, Radix::Float]
|
51
|
+
def b(base)
|
52
|
+
if index('.')
|
53
|
+
Radix::Float.new(self, base)
|
54
|
+
else
|
55
|
+
Radix::Integer.new(self, base)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Adds the b(base) method to this ruby class for quickly creating Radix
|
62
|
+
# instances.
|
63
|
+
class ::Array
|
64
|
+
|
65
|
+
##
|
66
|
+
# Takes array and makes it into a Radix::Integer or Radix::Float as given
|
67
|
+
# base. Float is determined by a "." character in array instance.
|
68
|
+
#
|
69
|
+
# @param [Fixnum, Array<String>] base
|
70
|
+
# The desired base.
|
71
|
+
#
|
72
|
+
# @return [Radix::Integer, Radix::Float]
|
73
|
+
def b(base)
|
74
|
+
if index('.')
|
75
|
+
Radix::Float.new(self, base)
|
76
|
+
else
|
77
|
+
Radix::Integer.new(self, base)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
data/lib/radix/rational.rb
CHANGED
@@ -3,31 +3,55 @@ require 'radix/numeric'
|
|
3
3
|
|
4
4
|
module Radix
|
5
5
|
|
6
|
+
##
|
6
7
|
# Represents rational numbers.
|
7
8
|
#
|
9
|
+
# @!attribute [r] value
|
10
|
+
# @return [Rational] Ruby Rational representation of self in Base-10.
|
11
|
+
# @!attribute [r] base
|
12
|
+
# @return [Fixnum] The base level of Rational instance.
|
13
|
+
# @!attribute [r] code
|
14
|
+
# @return [Array<String>, nil] Substitution chars or nil if default.
|
8
15
|
class Rational < Numeric
|
9
16
|
|
17
|
+
##
|
10
18
|
# Alternative to #new.
|
19
|
+
#
|
20
|
+
# @return [Radix::Rational]
|
11
21
|
def self.[](n,d=nil,b=10)
|
12
22
|
new(n,d,b)
|
13
23
|
end
|
14
24
|
|
15
|
-
|
25
|
+
##
|
26
|
+
# Stores the Rational value in Base-10.
|
27
|
+
#
|
28
|
+
# @return [Rational]
|
16
29
|
attr :value
|
17
30
|
|
31
|
+
##
|
18
32
|
# Base of the number.
|
33
|
+
#
|
34
|
+
# @return [Fixnum] The base level of Rational instance.
|
19
35
|
attr :base
|
20
36
|
|
37
|
+
##
|
21
38
|
# Base encoding table.
|
39
|
+
#
|
40
|
+
# @return [Array<String>, nil] Substitution chars or nil if default.
|
22
41
|
attr :code
|
23
42
|
|
24
43
|
private
|
25
44
|
|
45
|
+
##
|
26
46
|
# Create a new Radix::Rational instance.
|
27
|
-
#
|
47
|
+
# @example
|
28
48
|
# Rational.new(<Integer>, <Integer>, <Integer>)
|
29
49
|
# Rational.new(<Rational>, <Integer>)
|
30
|
-
#
|
50
|
+
# @param [Radix::Rational, ::Rational, Fixnum] numerator A rational number
|
51
|
+
# or a fixnum for the numerator of a new Rational.
|
52
|
+
# @param [Fixnum] denominator Denominator for new Rational.
|
53
|
+
# @param [Fixnum] base Base level for new Rational.
|
54
|
+
# @return [void]
|
31
55
|
def initialize(numerator, denominator=nil, base=10)
|
32
56
|
case numerator
|
33
57
|
when ::Rational, Rational
|
@@ -42,7 +66,11 @@ module Radix
|
|
42
66
|
@base, @code = parse_base(base)
|
43
67
|
end
|
44
68
|
|
45
|
-
|
69
|
+
##
|
70
|
+
# Parses String, Array, Radix::Float, Radix::Integer or Ruby numerics and
|
71
|
+
# returns the decimal value from base context for storage in @value.
|
72
|
+
#
|
73
|
+
# @param [Fixnum] base
|
46
74
|
def parse_value(value, base)
|
47
75
|
case value
|
48
76
|
when Float, Integer # Radix
|
@@ -58,38 +86,48 @@ module Radix
|
|
58
86
|
|
59
87
|
public
|
60
88
|
|
89
|
+
##
|
61
90
|
# The numerator.
|
62
91
|
#
|
92
|
+
# @return [Fixnum] The numerator of Radix::Rational
|
63
93
|
def numerator
|
64
94
|
@value.numerator
|
65
95
|
end
|
66
96
|
|
97
|
+
##
|
67
98
|
# The denominator.
|
68
99
|
#
|
100
|
+
# @return [Fixnum] The denominator of Radix::Rational
|
69
101
|
def denominator
|
70
102
|
@value.denominator
|
71
103
|
end
|
72
104
|
|
105
|
+
##
|
73
106
|
# Is the value negative?
|
74
107
|
#
|
108
|
+
# @return [Boolean] Returns true if value < 0.
|
75
109
|
def negative?
|
76
110
|
value < 0
|
77
111
|
end
|
78
112
|
|
113
|
+
##
|
79
114
|
# Convert rational to new base.
|
80
115
|
#
|
81
|
-
#
|
116
|
+
# @param [Fixnum] base Desired base.
|
117
|
+
# @return [Radix::Rational] Returns new Radix::Rational in passed base.
|
82
118
|
def convert(base)
|
83
119
|
self.class.new(numerator, denominator, base)
|
84
120
|
end
|
85
121
|
|
122
|
+
##
|
86
123
|
# Convert to rational.
|
87
124
|
#
|
88
|
-
# Returns the
|
125
|
+
# @return [Rational] Returns the value.
|
89
126
|
def to_r
|
90
127
|
value
|
91
128
|
end
|
92
129
|
|
130
|
+
##
|
93
131
|
# Convert to Float by dividing the numerator by the denominator.
|
94
132
|
#
|
95
133
|
# Returns the converted value. [Float]
|
@@ -97,6 +135,7 @@ module Radix
|
|
97
135
|
numerator.to_f / denominator.to_f
|
98
136
|
end
|
99
137
|
|
138
|
+
##
|
100
139
|
# Convert to Integer by converting to Float first then
|
101
140
|
# appling #to_i to the float.
|
102
141
|
#
|
@@ -105,9 +144,12 @@ module Radix
|
|
105
144
|
to_f.to_i
|
106
145
|
end
|
107
146
|
|
108
|
-
|
109
|
-
#
|
110
|
-
#
|
147
|
+
##
|
148
|
+
# Translate value into an array of places. Uses current base unless
|
149
|
+
# specified.
|
150
|
+
#
|
151
|
+
# @param [Fixnum] base Desired base.
|
152
|
+
# @return [Array<Fixnum, String>] Array of place values.
|
111
153
|
def to_a(base=nil)
|
112
154
|
if base
|
113
155
|
convert(base).digits_encoded
|
@@ -116,12 +158,12 @@ module Radix
|
|
116
158
|
end
|
117
159
|
end
|
118
160
|
|
161
|
+
##
|
119
162
|
# Convert the value into a string representation of the given base.
|
120
163
|
#
|
121
|
-
# base
|
122
|
-
# divider
|
123
|
-
#
|
124
|
-
# Returns translated value. [String]
|
164
|
+
# @param [Fixnum] base The base to convert.
|
165
|
+
# @param [String] divider The string char(s) to divided with.
|
166
|
+
# @return [String] Translated value.
|
125
167
|
def to_s(base=nil, divider=nil)
|
126
168
|
divider = divider.to_s if divider
|
127
169
|
if base
|
@@ -139,22 +181,33 @@ module Radix
|
|
139
181
|
end
|
140
182
|
end
|
141
183
|
|
142
|
-
|
143
|
-
#
|
144
|
-
# TODO: this may need improvement to be more percise.
|
184
|
+
##
|
185
|
+
# Simple equality requires equal values only.
|
145
186
|
#
|
146
|
-
#
|
187
|
+
# @todo This may need improvement to be more percise.
|
188
|
+
# @param [#to_f] other The value to compare to.
|
189
|
+
# @return [Boolean] True if equal values.
|
147
190
|
def ==(other)
|
148
191
|
a, b = self.to_f, other.to_f
|
149
192
|
a == b
|
150
193
|
end
|
151
194
|
|
152
|
-
|
195
|
+
##
|
196
|
+
# Returns an irreducible version of self in current base.
|
197
|
+
#
|
198
|
+
# @todo Is this method neccesary since @value is a Ruby Rational and
|
199
|
+
# therefore already irreducible?
|
200
|
+
# @return [Radix::Rational]
|
153
201
|
def reduce
|
154
202
|
self.class.new(Rational(numerator, denominator), base)
|
155
203
|
end
|
156
204
|
|
205
|
+
##
|
206
|
+
# Returns an array representation of the numerator and denominator with
|
207
|
+
# each column's value.
|
157
208
|
#
|
209
|
+
# @return [Array<String, Fixnum>] Values per column of @base as array.
|
210
|
+
# Prepended with "-" if negative.
|
158
211
|
def digits
|
159
212
|
n = base_conversion(numerator, base)
|
160
213
|
d = base_conversion(denominator, base)
|
@@ -163,34 +216,49 @@ module Radix
|
|
163
216
|
i
|
164
217
|
end
|
165
218
|
|
219
|
+
##
|
220
|
+
# Returns digits, or coded version of digits if @code.
|
166
221
|
#
|
222
|
+
# @return [Array<String, Fixnum>] Values per column of @base as array.
|
223
|
+
# Prepended with "-" if negative. Or encoded version if @code is
|
224
|
+
# defined.
|
167
225
|
def digits_encoded
|
168
226
|
base_encode(digits)
|
169
227
|
end
|
170
228
|
|
171
|
-
|
229
|
+
##
|
230
|
+
# Creates a string representation of self.
|
231
|
+
#
|
232
|
+
# @return [String] String rep of self.digits and @base.
|
172
233
|
def inspect
|
173
234
|
"#{digits.join(' ')} (#{base})"
|
174
235
|
end
|
175
236
|
|
176
|
-
|
237
|
+
##
|
238
|
+
# Returns new Radix::Rational of passed value in base-10 and self as an
|
239
|
+
# Array.
|
240
|
+
#
|
241
|
+
# @return [Array<(Radix::Rational, Radix::Rational)>]
|
177
242
|
def coerce(value)
|
178
243
|
[Radix::Rational.new(value), self]
|
179
244
|
end
|
180
245
|
|
181
246
|
private
|
182
247
|
|
183
|
-
|
248
|
+
##
|
249
|
+
# Perform passed arithmetic operation.
|
184
250
|
#
|
185
|
-
#
|
251
|
+
# @param [#to_r] other
|
252
|
+
# @return [Radix::Rational] Returns the result of the operation in @base.
|
186
253
|
def operation(op, other)
|
187
254
|
x = value.__send__(op, other.to_r)
|
188
255
|
self.class.new(x, base)
|
189
256
|
end
|
190
257
|
|
258
|
+
##
|
191
259
|
# Perform base conversion.
|
192
260
|
#
|
193
|
-
#
|
261
|
+
# @return [Array<Fixnum, String>] Array of places.
|
194
262
|
def base_conversion(value, base)
|
195
263
|
#if value < 0
|
196
264
|
# @negative, value = true, value.abs
|
@@ -213,11 +281,11 @@ module Radix
|
|
213
281
|
end
|
214
282
|
|
215
283
|
class ::Array
|
216
|
-
|
217
|
-
#
|
218
|
-
# TODO: Keep #br? Or find another way?
|
284
|
+
##
|
285
|
+
# Adds convenience method for creating a Radix::Rational.
|
219
286
|
#
|
220
|
-
#
|
287
|
+
# @todo Keep #br? Or find another way?
|
288
|
+
# @return [Radix::Rational]
|
221
289
|
def br(base=nil)
|
222
290
|
args = dup
|
223
291
|
args << base if base
|
@@ -227,6 +295,11 @@ end
|
|
227
295
|
|
228
296
|
if RUBY_VERSION < '1.9'
|
229
297
|
class ::Float
|
298
|
+
|
299
|
+
##
|
300
|
+
# Adds a #to_r method to pre-1.9 ruby Rationals.
|
301
|
+
#
|
302
|
+
# @return [Rational]
|
230
303
|
def to_r
|
231
304
|
n, f = to_s.split('.')
|
232
305
|
d = (10 ** f.size).to_i
|