7 
7 
#

8 
8 
# Documentation by Kevin Jackson and Gavin Sinclair.

9 
9 
#


10 
# Performance improvements by Kurt Stephens.


11 
#

10 
12 
# When you <tt>require 'rational'</tt>, all interactions between numbers

11 
13 
# potentially return a rational result. For example:

12 
14 
#

...  ...  
104 
106 
num = num

105 
107 
den = den

106 
108 
end

107 

if num.kind_of?(Integer) and den.kind_of?(Integer)

108 

@numerator = num

109 

@denominator = den

110 

else

111 

@numerator = num.to_i

112 

@denominator = den.to_i

113 

end


109 
@numerator = num.to_i


110 
@denominator = den.to_i

114 
111 
end

115 
112 

116 
113 
#

...  ...  
122 
119 
# r + 0.5 # > 1.25

123 
120 
#

124 
121 
def + (a)

125 

if a.kind_of?(Rational)

126 

num = @numerator * a.denominator

127 

num_a = a.numerator * @denominator

128 

Rational(num + num_a, @denominator * a.denominator)

129 

elsif a.kind_of?(Integer)

130 

self + Rational.new!(a, 1)

131 

elsif a.kind_of?(Float)

132 

Float(self) + a


122 
case a


123 
when Rational # => Rational  Integer


124 
Rational( (@numerator * a.denominator) + (a.numerator * @denominator), @denominator * a.denominator)


125 
when Integer # => Rational


126 
Rational.reduce((@numerator ) + (a * @denominator), @denominator)


127 
when Float


128 
self.to_f + a

133 
129 
else

134 
130 
x, y = a.coerce(self)

135 
131 
x + y

...  ...  
146 
142 
# r  0.5 # > 0.25

147 
143 
#

148 
144 
def  (a)

149 

if a.kind_of?(Rational)

150 

num = @numerator * a.denominator

151 

num_a = a.numerator * @denominator

152 

Rational(num  num_a, @denominator*a.denominator)

153 

elsif a.kind_of?(Integer)

154 

self  Rational.new!(a, 1)

155 

elsif a.kind_of?(Float)

156 

Float(self)  a


145 
case a


146 
when Rational # => Rational  Integer


147 
Rational( (@numerator * a.denominator)  (a.numerator * @denominator), @denominator * a.denominator)


148 
when Integer # => Rational


149 
Rational.reduce((@numerator )  (a * @denominator), @denominator)


150 
when Float


151 
self.to_f  a

157 
152 
else

158 
153 
x, y = a.coerce(self)

159 
154 
x  y

...  ...  
161 
156 
end

162 
157 

163 
158 
#


159 
# Unary MinusReturns the receiver's value, negated.


160 
#


161 
def @


162 
Rational.new!( @numerator, @denominator)


163 
end


164 


165 
#

164 
166 
# Returns the product of this value and +a+.

165 
167 
#

166 
168 
# Examples:

...  ...  
171 
173 
# r * Rational(1,2) # > Rational(3,8)

172 
174 
#

173 
175 
def * (a)

174 

if a.kind_of?(Rational)

175 

num = @numerator * a.numerator

176 

den = @denominator * a.denominator

177 

Rational(num, den)

178 

elsif a.kind_of?(Integer)

179 

self * Rational.new!(a, 1)

180 

elsif a.kind_of?(Float)

181 

Float(self) * a


176 
case a


177 
when Rational


178 
Rational(@numerator * a.numerator, @denominator * a.denominator)


179 
when Integer


180 
Rational(@numerator * a , @denominator)


181 
when Float


182 
self.to_f * a

182 
183 
else

183 
184 
x, y = a.coerce(self)

184 
185 
x * y

...  ...  
193 
194 
# r / Rational(1,2) # > Rational(3,2)

194 
195 
#

195 
196 
def / (a)

196 

if a.kind_of?(Rational)

197 

num = @numerator * a.denominator

198 

den = @denominator * a.numerator

199 

Rational(num, den)

200 

elsif a.kind_of?(Integer)


197 
case a


198 
when Rational


199 
Rational(@numerator * a.denominator, @denominator * a.numerator)


200 
when Integer

201 
201 
raise ZeroDivisionError, "division by zero" if a == 0

202 

self / Rational.new!(a, 1)

203 

elsif a.kind_of?(Float)

204 

Float(self) / a


202 
Rational(@numerator , @denominator * a )


203 
when Float


204 
self.to_f / a

205 
205 
else

206 
206 
x, y = a.coerce(self)

207 
207 
x / y

...  ...  
218 
218 
# r ** Rational(1,2) # > 0.866025403784439

219 
219 
#

220 
220 
def ** (other)

221 

if other.kind_of?(Rational)

222 

Float(self) ** other

223 

elsif other.kind_of?(Integer)


221 
case other


222 
when Rational, Float


223 
self.to_f ** other


224 
when Integer

224 
225 
if other > 0

225 

num = @numerator ** other

226 

den = @denominator ** other


226 
Rational.new!(@numerator ** other, @denominator ** other)

227 
227 
elsif other < 0

228 

num = @denominator ** other

229 

den = @numerator ** other

230 

elsif other == 0

231 

num = 1

232 

den = 1


228 
Rational.new!(@denominator ** other, @numerator ** other)


229 
else


230 
Rational.new!(1, 1) # why not Fixnum 1?

233 
231 
end

234 

Rational.new!(num, den)

235 

elsif other.kind_of?(Float)

236 

Float(self) ** other

237 
232 
else

238 
233 
x, y = other.coerce(self)

239 
234 
x ** y

...  ...  
256 
251 
#

257 
252 
def % (other)

258 
253 
value = (self / other).floor

259 

return self  other * value


254 
self  other * value

260 
255 
end

261 
256 

262 
257 
#

...  ...  
268 
263 
#

269 
264 
def divmod(other)

270 
265 
value = (self / other).floor

271 

return value, self  other * value


266 
[ value, self  other * value ]

272 
267 
end

273 
268 

274 
269 
#

...  ...  
282 
277 
end

283 
278 
end

284 
279 


280 
# Returns true or false.


281 
def zero?


282 
@numerator.zero?


283 
end


284 


285 
# See Numeric#nonzero?


286 
def nonzero?


287 
@numerator.nonzero? ? self : nil


288 
end


289 


290 

285 
291 
#

286 
292 
# Returns +true+ iff this value is numerically equal to +other+.

287 
293 
#

...  ...  
292 
298 
# Don't use Rational.new!

293 
299 
#

294 
300 
def == (other)

295 

if other.kind_of?(Rational)


301 
case other


302 
when Rational

296 
303 
@numerator == other.numerator and @denominator == other.denominator

297 

elsif other.kind_of?(Integer)

298 

self == Rational.new!(other, 1)

299 

elsif other.kind_of?(Float)

300 

Float(self) == other


304 
when Integer


305 
@numerator == other && @denominator == 1


306 
when Float


307 
self.to_f == other

301 
308 
else

302 
309 
other == self

303 
310 
end

...  ...  
307 
314 
# Standard comparison operator.

308 
315 
#

309 
316 
def <=> (other)

310 

if other.kind_of?(Rational)

311 

num = @numerator * other.denominator

312 

num_a = other.numerator * @denominator

313 

v = num  num_a

314 

if v > 0

315 

return 1

316 

elsif v < 0

317 

return 1

318 

else

319 

return 0

320 

end

321 

elsif other.kind_of?(Integer)

322 

return self <=> Rational.new!(other, 1)

323 

elsif other.kind_of?(Float)

324 

return Float(self) <=> other

325 

elsif defined? other.coerce

326 

x, y = other.coerce(self)

327 

return x <=> y


317 
case other


318 
when Rational


319 
((@numerator * other.denominator) <=> (other.numerator * @denominator))


320 
when Integer


321 
((@numerator ) <=> (other * @denominator))


322 
when Float


323 
self.to_f <=> other

328 
324 
else

329 

return nil


325 
if defined? other.coerce


326 
x, y = other.coerce(self)


327 
x <=> y


328 
end # nil

330 
329 
end

331 
330 
end

332 
331 

333 
332 
def coerce(other)

334 

if other.kind_of?(Float)

335 

return other, self.to_f

336 

elsif other.kind_of?(Integer)

337 

return Rational.new!(other, 1), self


333 
case other


334 
when Float


335 
[ other, self.to_f ]


336 
when Integer


337 
[ Rational.new!(other, 1), self ]

338 
338 
else

339 
339 
super

340 
340 
end

...  ...  
363 
363 

364 
364 
def truncate()

365 
365 
if @numerator < 0

366 

return ((@numerator).div(@denominator))


366 
((@numerator).div(@denominator))


367 
else


368 
@numerator.div(@denominator)

367 
369 
end

368 

@numerator.div(@denominator)

369 
370 
end

370 
371 

371 
372 
alias_method :to_i, :truncate

372 
373 

373 
374 
def round()

374 
375 
if @numerator < 0

375 

num = @numerator

376 

num = num * 2 + @denominator

377 

den = @denominator * 2

378 

(num.div(den))


376 
((@numerator * 2 + @denominator).div(@denominator * 2))

379 
377 
else

380 

num = @numerator * 2 + @denominator

381 

den = @denominator * 2

382 

num.div(den)


378 
((@numerator * 2 + @denominator).div(@denominator * 2))

383 
379 
end

384 
380 
end

385 
381 

...  ...  
401 
397 
if @denominator == 1

402 
398 
@numerator.to_s

403 
399 
else

404 

@numerator.to_s+"/"+@denominator.to_s


400 
"#{@numerator}/#{@denominator}"

405 
401 
end

406 
402 
end

407 
403 

...  ...  
418 
414 
# Rational(5,8).inspect # > "Rational(5, 8)"

419 
415 
#

420 
416 
def inspect

421 

sprintf("Rational(%s, %s)", @numerator.inspect, @denominator.inspect)


417 
"Rational(#{@numerator.inspect}, #{@denominator.inspect})"

422 
418 
end

423 
419 

424 
420 
#
