Class: RationalNumber

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/rational_number.rb

Overview

< Object

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(a = nil, b = nil, c = nil, d = nil) ⇒ undefined

Initialize rational number

Parameters:

  • The (Integer/RationalNumber)

    nominator value or a rational number, depending on number of given parameters

  • The (Integer)

    denominator value

  • The (Integer)

    SNV value

  • The (Integer)

    SDV Value



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rational_number.rb', line 70

def initialize(a = nil, b = nil, c = nil, d = nil)
  if a == nil and b == nil and c == nil and d == nil
    init_with_4_args()
  elsif b == nil and c == nil and d == nil
    init_with_1_arg(a)
  elsif c == nil and d == nil
    init_with_2_args(a,b)
  else
    init_with_4_args(a,b,c,d)
  end
end

Instance Attribute Details

#dvObject (readonly)

Returns the value of attribute dv.



19
20
21
# File 'lib/rational_number.rb', line 19

def dv
  @dv
end

#numberObject (readonly)

Returns the value of attribute number.



19
20
21
# File 'lib/rational_number.rb', line 19

def number
  @number
end

#nvObject (readonly)

Returns the value of attribute nv.



19
20
21
# File 'lib/rational_number.rb', line 19

def nv
  @nv
end

#sdvObject (readonly)

Returns the value of attribute sdv.



19
20
21
# File 'lib/rational_number.rb', line 19

def sdv
  @sdv
end

#snvObject (readonly)

Returns the value of attribute snv.



19
20
21
# File 'lib/rational_number.rb', line 19

def snv
  @snv
end

Instance Method Details

#<=>(other) ⇒ Integer

Compare to other (Comparable) Returns 1 if greater than, -1 if less than, and 0 for equality

Returns:

  • (Integer)

    Integer stating the comparison.



27
28
29
30
31
32
33
34
# File 'lib/rational_number.rb', line 27

def <=>(other)
  return 0 if (@nv === other.nv) and (@dv === other.dv) and (@snv == other.snv) and (@sdv == other.sdv)
  if @number < other.number
    -1
  elsif @number > other.number
    1
  end
end

#child_from_position(_position) ⇒ RationalNumber

Return the child rational number from given position

Parameters:

  • The (Integer)

    position

Returns:



268
269
270
# File 'lib/rational_number.rb', line 268

def child_from_position(_position)
  value_from_parent_and_position(self, _position)
end

#init_with_1_arg(rational_number) ⇒ undefined

Initialize rational number with 1 argument

Parameters:

Returns:

  • (undefined)

Raises:

  • (ArgumentError)


89
90
91
92
# File 'lib/rational_number.rb', line 89

def init_with_1_arg(rational_number)
  raise ArgumentError, "given :rational_number in options is of wrong type, should be RationalNumber" unless rational_number.instance_of?(RationalNumber)
  set_values(rational_number.nv, rational_number.dv, rational_number.snv, rational_number.sdv)
end

#init_with_2_args(nv = 0, dv = 1) ⇒ undefined

Initialize rational number with 2 arguments

Parameters:

  • The (Integer)

    nominator value

  • The (Integer)

    denominator value

Returns:

  • (undefined)

Raises:

  • (ArgumentError)


102
103
104
105
106
107
108
109
110
111
# File 'lib/rational_number.rb', line 102

def init_with_2_args(nv = 0, dv = 1)
  raise ArgumentError, ":nv and :dv must be kind_of?(Integer)." unless nv.kind_of?(Integer) and dv.kind_of?(Integer)
  # initial values needed when getting parent and position
  @nv = nv
  @dv = dv
  # calculate value
  val = value_from_parent_and_position(self.parent, self.position)
  raise ArgumentError, "Cannot set nv and dv values. verify the values for :nv and :dv" unless ((val.nv == nv) and (val.dv == dv))
  set_values(val.nv,val.dv,val.snv,val.sdv)
end

#init_with_4_args(nv = 0, dv = 1, snv = 1, sdv = 0) ⇒ undefined

Initialize rational number with 4 arguments

Parameters:

  • The (Integer)

    nominator value

  • The (Integer)

    denominator value

  • The (Integer)

    SNV value

  • The (Integer)

    SDV Value

Returns:

  • (undefined)


123
124
125
126
127
128
# File 'lib/rational_number.rb', line 123

def init_with_4_args(nv = 0, dv = 1, snv = 1, sdv = 0)
  unless nv.kind_of?(Integer) and dv.kind_of?(Integer) and snv.kind_of?(Integer) and sdv.kind_of?(Integer)
    raise ArgumentError, ":nv, :dv, :snv and :sdv must be kind_of?(Integer)."
  end
  set_values(nv, dv, snv, sdv)
end

#is_child_of?(_parent) ⇒ Boolean

Check if the child is a immediate child of an parent

Parameters:

Returns:

  • (Boolean)

    true if the parent to verify against is the same as the childs parent



279
280
281
282
# File 'lib/rational_number.rb', line 279

def is_child_of?(_parent)
  return false if (self == _parent) or self.root?
  _parent == self.parent
end

#is_descendant_of?(_parent) ⇒ Boolean

Check if the child is a descendant of an parent (at any level)

Parameters:

Returns:

  • (Boolean)

    true if the parent is any parent above in the hierarchy



303
304
305
306
307
308
309
310
311
# File 'lib/rational_number.rb', line 303

def is_descendant_of?(_parent)
  return false if (self == _parent) or self.root?
  verify_parent = self # start with beeing self
  while !verify_parent.root? do
    verify_parent = verify_parent.parent
    return true if _parent == verify_parent
  end
  false
end

#is_parent_of?(_child) ⇒ Boolean

Check if the parent is a immediate parent of a child

Parameters:

Returns:

  • (Boolean)

    true if the parent to verify against is the same as the childs parent



291
292
293
294
# File 'lib/rational_number.rb', line 291

def is_parent_of?(_child)
  return false if self == _child
  _child.is_child_of?(self)
end

#next_siblingRationalNumber

Return the next sibling rational number

Uses this RationalNumber parent values

Returns:

Raises:



220
221
222
223
224
225
226
227
# File 'lib/rational_number.rb', line 220

def next_sibling
  # Raise error in case we are root
  raise RationalNumberIsRootNoSiblingsError if root?

  _parent = self.parent # Get parent already to avoid duplicate calculations
  _position = ((@nv - _parent.nv) / _parent.snv) + 1
  value_from_parent_and_position(_parent, _position)
end

#parentRationalNumber

Returns parent as a rational number

Returns:

Raises:



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/rational_number.rb', line 183

def parent
  raise NoParentRationalNumberIsRootError if root?
  numerator   = @nv
  denominator = @dv
  _parent    = RationalNumber.new
  compare_key  = RationalNumber.new
  # make sure we break if we get root values! (numerator == 0 + denominator == 0)
  while ((compare_key.nv < @nv) && (compare_key.dv < @dv)) && ((numerator > 0) && (denominator > 0))
    div = numerator / denominator
    mod = numerator % denominator
    # set return values to previous values, as they are the parent values
    _parent.set_from_other(compare_key)

    # temporary calculations (needed)
    parent_nv = _parent.nv + (div * _parent.snv)
    parent_dv = _parent.dv + (div * _parent.sdv)

    compare_key.set_values( parent_nv ,  #nv
                            parent_dv ,  #dv
                            parent_nv + _parent.snv, #snv
                            parent_dv + _parent.sdv) #sdv
    numerator = mod
    if (numerator != 0)
      denominator = denominator % mod
      denominator = 1 if denominator == 0
    end
  end
  _parent
end

#positionInteger

Get the calculated postion at the current “level” for this rational number in a “tree”

Returns:

  • (Integer)

    The position



173
174
175
176
# File 'lib/rational_number.rb', line 173

def position
  _parent = self.parent
  ((@nv - _parent.nv) / _parent.snv)
end

#root?Boolean

See if rational number is root

Returns:

  • (Boolean)


164
165
166
# File 'lib/rational_number.rb', line 164

def root?
  (@nv === 0) and (@dv === 1) and (@snv === 1) and (@sdv === 0)
end

#set_from_other(other) ⇒ undefined

Will set the values from another RationalNumber

Parameters:

Returns:

  • (undefined)


157
158
159
# File 'lib/rational_number.rb', line 157

def set_from_other(other)
  set_values(other.nv, other.dv, other.snv, other.sdv)
end

#set_values(nv, dv, snv, sdv) ⇒ Object

Set the values of nv,dv,snv and sdv directly

Parameters:

  • The (Integer)

    nominator value

  • The (Integer)

    denominator value

  • The (Integer)

    SNV value

  • The (Integer)

    SDV Value



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/rational_number.rb', line 138

def set_values(nv, dv, snv, sdv)
  @nv = nv
  @dv = dv
  @snv = snv
  @sdv = sdv
  if nv == 0 and dv == 0
    @number = BigDecimal(0)
  else
    @number = BigDecimal(nv)/BigDecimal(dv)
  end
end

#sibling_from_position(_position) ⇒ RationalNumber

Return the sibling rational number from a given position.

Uses this RationalNumber parent values

Parameters:

  • The (Integer)

    position

Returns:

Raises:



238
239
240
241
242
# File 'lib/rational_number.rb', line 238

def sibling_from_position(_position)
  raise RationalNumberIsRootNoSiblingsError if root?
  _parent = self.parent
  value_from_parent_and_position(_parent, _position)
end

#to_hashHash

Convert to Hash

Returns:

  • (Hash)

    hash containing the rational numbers



50
51
52
53
54
55
56
57
58
# File 'lib/rational_number.rb', line 50

def to_hash
  {
    :nv => @nv,
    :dv => @dv,
    :snv => @snv,
    :sdv => @sdv,
    :number => @number
  }
end

#to_sString

Convert to string

Returns:

  • (String)

    String describing the rational number.



41
42
43
# File 'lib/rational_number.rb', line 41

def to_s
  "RationalNumber: number: #{@number} nv: #{@nv} dv: #{@dv} snv: #{@snv} sdv: #{@sdv}"
end

#value_from_parent_and_position(_parent, _position) ⇒ RationalNumber

Return the rational number from parent and position

Parameters:

  • The (RationalNumber)

    parents RationalNumber for a given RationalNumber and the new sibling

  • The (Integer)

    position

Returns:



252
253
254
255
256
257
258
259
# File 'lib/rational_number.rb', line 252

def value_from_parent_and_position(_parent, _position)
  sibling = RationalNumber.new(
    _parent.nv + (_position * _parent.snv), # nv
    _parent.dv + (_position * _parent.sdv), # dv
    _parent.nv + ((_position + 1) * _parent.snv), # snv
    _parent.dv + ((_position + 1) * _parent.sdv)  # sdv
    )
end