Class: Radix::Numeric

Inherits:
Numeric
  • Object
show all
Defined in:
lib/radix/numeric.rb

Overview

TODO:

Make immutable, but best way to do it?

Radix::Numeric class inherits from Ruby’s Numeric class. It is then subclassed by Radix::Integer and Radix::Float.

Examples:

First suggestion

class << self
  alias_method :_new, :new
  private :_new
end

Second suggestion

def self.new(value, base=10)
  @cache ||= {}
  @cache[[value, base]] ||= _new(value, base)
end

Direct Known Subclasses

Float, Integer, Rational

Instance Method Summary collapse

Instance Method Details

#*(other) ⇒ Radix::Numeric

Multiplication, binary operation.



57
58
59
# File 'lib/radix/numeric.rb', line 57

def *(other)
  operation(:*, other)
end

#+(other) ⇒ Radix::Numeric

Addition, binary operation.



37
38
39
# File 'lib/radix/numeric.rb', line 37

def +(other)
  operation(:+, other)
end

#-(other) ⇒ Radix::Numeric

Subtraction, binary operation.



47
48
49
# File 'lib/radix/numeric.rb', line 47

def -(other)
  operation(:-, other)
end

#/(other) ⇒ Radix::Numeric

Division, binary operation.



67
68
69
# File 'lib/radix/numeric.rb', line 67

def /(other)
  operation(:/, other)
end

#base_decode(digits) ⇒ Array<String, Numeric> (private)

Decode an encoded array. Defaults to BASE::B62 if @code is not set.



200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/radix/numeric.rb', line 200

def base_decode(digits)
  #return digits unless code
  code = self.code || BASE::B62
  digits.map do |c|
    case c
    when '-', DOT, DIV
      c
    when ::Numeric
      c
    else
      code.index(c)  # TODO: Could speed up with an reverse index.
    end
  end
end

#base_encode(digits) ⇒ Array<String, Fixnum> (private)

Map array of values to base encoding. If no encoding is defined this simply returns the digits unchanged.



182
183
184
185
186
187
188
189
190
191
192
# File 'lib/radix/numeric.rb', line 182

def base_encode(digits)
  return digits unless @code
  digits.map do |i|
    case i
    when '-', DOT, DIV
      i
    else
      code[i]
    end
  end
end

#decimal(digits, base) ⇒ Integer (private)

Convert array of values of a different base to decimal. This handles integer values. The method for Radix::Float is slighly different.



165
166
167
168
169
170
171
172
173
# File 'lib/radix/numeric.rb', line 165

def decimal(digits, base)
  e = digits.size - 1
  v = 0
  digits.each do |n|
    v += n.to_i * base**e
    e -= 1
  end
  v
end

#parse_array(value, base) ⇒ Fixnum (private)

Take an Array in the form of [d1, d2, …, DOT, d-1, d-2, …] and convert it to base ten, and store in @value.

Raises:

  • (ArgumentError)


134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/radix/numeric.rb', line 134

def parse_array(value, base)
  value = value.dup

  if value.first == '-'
    neg = true
    value.shift
  else
    neg = false
  end

  value = base_decode(value)

  ## raise an error if any digit is not less than base
  raise ArgumentError if value.any?{ |e| ::Numeric === e && base < e }

  v = decimal(value, base)

  neg ? -v : v # Returns negated v if value array.first == "-"
end

#parse_base(base) ⇒ Array<(Fixnum, [Array<String>, nil])> (private)

Note:

If an array of String characters is passed, its length is the value of the base level.

Parses the value of the base and character set to use.



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/radix/numeric.rb', line 86

def parse_base(base)
  case base
  when Array
    code = base
    base = base.size
  else
    code = nil
    base = base
  end
  return base, code
end

#parse_numeric(value, base) ⇒ Radix::Float, Radix::Integer (private)

Simply returns the passed value. Used for simplifying creation of Radix::Numeric instances.



106
107
108
# File 'lib/radix/numeric.rb', line 106

def parse_numeric(value, base)
  value
end

#parse_string(value, base) ⇒ Radix::Float, Radix::Integer (private)

If a float style string is passed in for value, e.g. “9.5”, the decimal will simply be truncated. So “9.x” would become “9”.



121
122
123
124
# File 'lib/radix/numeric.rb', line 121

def parse_string(value, base)
  digits = value.split(//)
  parse_array(digits, base)
end