1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
class Rational < Numeric
# Override #<, #<=, #>, #>= in Numeric
prepend Comparable
def initialize(numerator = 0, denominator = 1)
@numerator = numerator
@denominator = denominator
_simplify
end
def inspect
"(#{to_s})"
end
def to_f
@numerator.to_f / @denominator.to_f
end
def to_i
to_f.to_i
end
def to_r
self
end
def to_s
"#{numerator}/#{denominator}"
end
def *(rhs)
if rhs.is_a? Rational
Rational(numerator * rhs.numerator, denominator * rhs.denominator)
elsif rhs.is_a? Integer
Rational(numerator * rhs, denominator)
elsif rhs.is_a? Numeric
numerator * rhs / denominator
end
end
def +(rhs)
if rhs.is_a? Rational
Rational(numerator * rhs.denominator + rhs.numerator * denominator, denominator * rhs.denominator)
elsif rhs.is_a? Integer
Rational(numerator + rhs * denominator, denominator)
elsif rhs.is_a? Numeric
(numerator + rhs * denominator) / denominator
end
end
def -(rhs)
if rhs.is_a? Rational
Rational(numerator * rhs.denominator - rhs.numerator * denominator, denominator * rhs.denominator)
elsif rhs.is_a? Integer
Rational(numerator - rhs * denominator, denominator)
elsif rhs.is_a? Numeric
(numerator - rhs * denominator) / denominator
end
end
def /(rhs)
if rhs.is_a? Rational
Rational(numerator * rhs.denominator, denominator * rhs.numerator)
elsif rhs.is_a? Integer
Rational(numerator, denominator * rhs)
elsif rhs.is_a? Numeric
numerator / rhs / denominator
end
end
def <=>(rhs)
case rhs
when Fixnum
return numerator <=> rhs if denominator == 1
rhs = Rational(rhs)
when Float
return to_f <=> rhs
end
case rhs
when Rational
(numerator * rhs.denominator - denominator * rhs.numerator) <=> 0
when Numeric
return rhs <=> self
else
nil
end
end
def negative?
numerator.negative?
end
def _simplify
a = numerator
b = denominator
a, b = b, a % b until b.zero?
@numerator = @numerator.div(a)
@denominator = @denominator.div(a)
end
attr_reader :numerator, :denominator
end
def Rational(numerator = 0, denominator = 1)
Rational.new(numerator, denominator)
end
[:+, :-, :*, :/, :<=>, :==, :<, :<=, :>, :>=].each do |op|
Fixnum.instance_exec do
original_operator_name = "__original_operator_#{op}_rational"
alias_method original_operator_name, op
define_method op do |rhs|
if rhs.is_a? Rational
Rational(self).__send__(op, rhs)
else
__send__(original_operator_name, rhs)
end
end
end
Float.instance_exec do
original_operator_name = "__original_operator_#{op}_rational"
alias_method original_operator_name, op
define_method op do |rhs|
if rhs.is_a? Rational
rhs = rhs.to_f
end
__send__(original_operator_name, rhs)
end
end
end
|