Class: MM::Ratio
- Inherits:
-
Object
- Object
- MM::Ratio
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/mm/ratio.rb
Instance Attribute Summary collapse
-
#denominator ⇒ Object
Returns the value of attribute denominator.
-
#numerator ⇒ Object
Returns the value of attribute numerator.
Class Method Summary collapse
- .change_interval(point, index, interval) ⇒ Object
- .from_s(r) ⇒ Object
- .from_vector(vector) ⇒ Object
-
.from_yaml(yaml_string) ⇒ Object
Loads a sequence of MM::Ratios from a YAML file.
- .string_to_ratio(string) ⇒ Object
- .to_vector(point) ⇒ Object
Instance Method Summary collapse
- #*(other) ⇒ Object
- #+(other) ⇒ Object
- #-(other) ⇒ Object
- #/(other) ⇒ Object
- #<=>(other) ⇒ Object
- #[](i) ⇒ Object
- #abs ⇒ Object
- #cents ⇒ Object
- #each ⇒ Object
- #eql?(other) ⇒ Boolean
-
#factors ⇒ Object
Works very similarly to the Prime::prime_division method, except that factors in the numerator are positive, and factors in the denominator are negative.
- #hash ⇒ Object
-
#initialize(n, d) ⇒ Ratio
constructor
A new instance of Ratio.
- #prime_limit ⇒ Object
- #reciprocal ⇒ Object
- #to_f ⇒ Object
- #to_s ⇒ Object
Constructor Details
#initialize(n, d) ⇒ Ratio
Returns a new instance of Ratio.
10 11 12 13 14 |
# File 'lib/mm/ratio.rb', line 10 def initialize n, d gcd = n.gcd d @numerator = n / gcd @denominator = d / gcd end |
Instance Attribute Details
#denominator ⇒ Object
Returns the value of attribute denominator.
16 17 18 |
# File 'lib/mm/ratio.rb', line 16 def denominator @denominator end |
#numerator ⇒ Object
Returns the value of attribute numerator.
16 17 18 |
# File 'lib/mm/ratio.rb', line 16 def numerator @numerator end |
Class Method Details
.change_interval(point, index, interval) ⇒ Object
147 148 149 150 151 152 153 154 |
# File 'lib/mm/ratio.rb', line 147 def self.change_interval point, index, interval vector = MM::Ratio.to_vector(point) if interval == :reciprocal interval = vector[index].reciprocal end vector[index] = interval MM::Ratio.from_vector(vector) end |
.from_s(r) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/mm/ratio.rb', line 85 def self.from_s r if r.respond_to? :split if r =~ /\s/ r.split(/\s/).inject([]) {|memo, ratio| memo << self.from_s(ratio) } else string_to_ratio r end else r.map {|s| self.from_s s} end end |
.from_vector(vector) ⇒ Object
143 144 145 |
# File 'lib/mm/ratio.rb', line 143 def self.from_vector vector vector.inject([MM::Ratio.new(1,1)]) {|m, r| m << (m.last / r)} end |
.from_yaml(yaml_string) ⇒ Object
Loads a sequence of MM::Ratios from a YAML file.
105 106 107 |
# File 'lib/mm/ratio.rb', line 105 def self.from_yaml yaml_string YAML.load(yaml_string).map {|r| MM::Ratio.from_s r} end |
.string_to_ratio(string) ⇒ Object
99 100 101 102 |
# File 'lib/mm/ratio.rb', line 99 def self.string_to_ratio string m = string.match(/(\d+)\/(\d+)/) MM::Ratio.new(m[1].to_i, m[2].to_i) end |
.to_vector(point) ⇒ Object
139 140 141 |
# File 'lib/mm/ratio.rb', line 139 def self.to_vector point point.each_cons(2).map {|r| r[0] / r[1]} end |
Instance Method Details
#*(other) ⇒ Object
18 19 20 |
# File 'lib/mm/ratio.rb', line 18 def * other MM::Ratio.new(self.numerator * other.numerator, self.denominator * other.denominator) end |
#+(other) ⇒ Object
26 27 28 29 |
# File 'lib/mm/ratio.rb', line 26 def + other MM::Ratio.new(self.numerator*other.denominator + other.numerator*self.denominator, self.denominator*other.denominator) end |
#-(other) ⇒ Object
31 32 33 |
# File 'lib/mm/ratio.rb', line 31 def - other self + (other * MM::Ratio.new(-1,1)) end |
#/(other) ⇒ Object
22 23 24 |
# File 'lib/mm/ratio.rb', line 22 def / other self * other.reciprocal end |
#<=>(other) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/mm/ratio.rb', line 60 def <=> other # Ensure that the comparison makes sense return nil unless other.respond_to? :- case when (self - other).to_f > 0 return 1 when (self - other).to_f < 0 return -1 end return 0 end |
#[](i) ⇒ Object
35 36 37 38 39 40 41 |
# File 'lib/mm/ratio.rb', line 35 def [] i if i == 0 self.numerator elsif i == 1 self.denominator end end |
#abs ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/mm/ratio.rb', line 52 def abs if self < MM::Ratio.new(0, 1) self * MM::Ratio.new(-1,1) else self end end |
#cents ⇒ Object
81 82 83 |
# File 'lib/mm/ratio.rb', line 81 def cents Math.log2(self.to_f) * 1200.0 end |
#each ⇒ Object
129 130 131 132 133 134 135 136 137 |
# File 'lib/mm/ratio.rb', line 129 def each if block_given? [@numerator, @denominator].each do |r| yield r end else [@numerator, @denominator].each end end |
#eql?(other) ⇒ Boolean
73 74 75 |
# File 'lib/mm/ratio.rb', line 73 def eql? other other.is_a?(MM::Ratio) && (self == other) end |
#factors ⇒ Object
Works very similarly to the Prime::prime_division method, except that factors in the numerator are positive, and factors in the denominator are negative.
46 47 48 49 50 |
# File 'lib/mm/ratio.rb', line 46 def factors n_factors = ::Prime.prime_division(@numerator) d_factors = ::Prime.prime_division(@denominator).map {|d| d[1] *= -1; d} n_factors.concat(d_factors).sort_by {|x| x[0]} end |
#hash ⇒ Object
77 78 79 |
# File 'lib/mm/ratio.rb', line 77 def hash [@numerator, @denominator, MM::Ratio].hash end |
#prime_limit ⇒ Object
121 122 123 124 125 126 127 |
# File 'lib/mm/ratio.rb', line 121 def prime_limit self.map { |r| r.prime_division.map { |s| s.first }.max }.compact.max end |
#reciprocal ⇒ Object
117 118 119 |
# File 'lib/mm/ratio.rb', line 117 def reciprocal MM::Ratio.new(@denominator, @numerator) end |
#to_f ⇒ Object
109 110 111 |
# File 'lib/mm/ratio.rb', line 109 def to_f @numerator.to_f / @denominator end |
#to_s ⇒ Object
113 114 115 |
# File 'lib/mm/ratio.rb', line 113 def to_s "#{@numerator}/#{@denominator}" end |