Class Rational
In: lib/mathn.rb
lib/rational.rb
Parent: Object

Rational implements a rational class for numbers.

A rational number is a number that can be expressed as a fraction p/q where p and q are integers and q != 0. A rational number p/q is said to have numerator p and denominator q. Numbers that are not rational are called irrational numbers. (mathworld.wolfram.com/RationalNumber.html)

To create a Rational Number:

  Rational(a,b)             # -> a/b
  Rational.new!(a,b)        # -> a/b

Examples:

  Rational(5,6)             # -> 5/6
  Rational(5)               # -> 5/1

Rational numbers are reduced to their lowest terms:

  Rational(6,10)            # -> 3/5

But not if you use the unusual method "new!":

  Rational.new!(6,10)       # -> 6/10

Division by zero is obviously not allowed:

  Rational(3,0)             # -> ZeroDivisionError

Methods

%   *   **   **   +   -   /   <=>   ==   abs   ceil   coerce   div   divmod   floor   hash   inspect   inspect   new   new!   power2   reduce   round   to_f   to_i   to_r   to_s   truncate  

Constants

Unify = true

External Aliases

** -> power!

Attributes

denominator  [R] 
numerator  [R] 

Public Class methods

This method is actually private.

[Source]

     # File lib/rational.rb, line 102
102:   def initialize(num, den)
103:     if den < 0
104:       num = -num
105:       den = -den
106:     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
114:   end

Implements the constructor. This method does not reduce to lowest terms or check for division by zero. Therefore Rational() should be preferred in normal use.

[Source]

    # File lib/rational.rb, line 93
93:   def Rational.new!(num, den = 1)
94:     new(num, den)
95:   end

Reduces the given numerator and denominator to their lowest terms. Use Rational() instead.

[Source]

    # File lib/rational.rb, line 71
71:   def Rational.reduce(num, den = 1)
72:     raise ZeroDivisionError, "denominator is zero" if den == 0
73: 
74:     if den < 0
75:       num = -num
76:       den = -den
77:     end
78:     gcd = num.gcd(den)
79:     num = num.div(gcd)
80:     den = den.div(gcd)
81:     if den == 1 && defined?(Unify)
82:       num
83:     else
84:       new!(num, den)
85:     end
86:   end

Public Instance methods

Returns the remainder when this value is divided by other.

Examples:

  r = Rational(7,4)    # -> Rational(7,4)
  r % Rational(1,2)    # -> Rational(1,4)
  r % 1                # -> Rational(3,4)
  r % Rational(1,7)    # -> Rational(1,28)
  r % 0.26             # -> 0.19

[Source]

     # File lib/rational.rb, line 257
257:   def % (other)
258:     value = (self / other).floor
259:     return self - other * value
260:   end

Returns the product of this value and a.

Examples:

  r = Rational(3,4)    # -> Rational(3,4)
  r * 2                # -> Rational(3,2)
  r * 4                # -> Rational(3,1)
  r * 0.5              # -> 0.375
  r * Rational(1,2)    # -> Rational(3,8)

[Source]

     # File lib/rational.rb, line 173
173:   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
182:     else
183:       x, y = a.coerce(self)
184:       x * y
185:     end
186:   end

[Source]

     # File lib/mathn.rb, line 126
126:   def ** (other)
127:     if other.kind_of?(Rational)
128:       other2 = other
129:       if self < 0
130:         return Complex.new!(self, 0) ** other
131:       elsif other == 0
132:         return Rational(1,1)
133:       elsif self == 0
134:         return Rational(0,1)
135:       elsif self == 1
136:         return Rational(1,1)
137:       end
138:       
139:       npd = numerator.prime_division
140:       dpd = denominator.prime_division
141:       if other < 0
142:         other = -other
143:         npd, dpd = dpd, npd
144:       end
145:       
146:       for elm in npd
147:         elm[1] = elm[1] * other
148:         if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
149:          return Float(self) ** other2
150:         end
151:         elm[1] = elm[1].to_i
152:       end
153:       
154:       for elm in dpd
155:         elm[1] = elm[1] * other
156:         if !elm[1].kind_of?(Integer) and elm[1].denominator != 1
157:          return Float(self) ** other2
158:         end
159:         elm[1] = elm[1].to_i
160:       end
161:       
162:       num = Integer.from_prime_division(npd)
163:       den = Integer.from_prime_division(dpd)
164:       
165:       Rational(num,den)
166:       
167:     elsif other.kind_of?(Integer)
168:       if other > 0
169:         num = numerator ** other
170:         den = denominator ** other
171:       elsif other < 0
172:         num = denominator ** -other
173:         den = numerator ** -other
174:       elsif other == 0
175:         num = 1
176:         den = 1
177:       end
178:       Rational.new!(num, den)
179:     elsif other.kind_of?(Float)
180:       Float(self) ** other
181:     else
182:       x , y = other.coerce(self)
183:       x ** y
184:     end
185:   end

Returns this value raised to the given power.

Examples:

  r = Rational(3,4)    # -> Rational(3,4)
  r ** 2               # -> Rational(9,16)
  r ** 2.0             # -> 0.5625
  r ** Rational(1,2)   # -> 0.866025403784439

[Source]

     # File lib/rational.rb, line 220
220:   def ** (other)
221:     if other.kind_of?(Rational)
222:       Float(self) ** other
223:     elsif other.kind_of?(Integer)
224:       if other > 0
225:         num = @numerator ** other
226:         den = @denominator ** other
227:       elsif other < 0
228:         num = @denominator ** -other
229:         den = @numerator ** -other
230:       elsif other == 0
231:         num = 1
232:         den = 1
233:       end
234:       Rational.new!(num, den)
235:     elsif other.kind_of?(Float)
236:       Float(self) ** other
237:     else
238:       x, y = other.coerce(self)
239:       x ** y
240:     end
241:   end

Returns the addition of this value and a.

Examples:

  r = Rational(3,4)      # -> Rational(3,4)
  r + 1                  # -> Rational(7,4)
  r + 0.5                # -> 1.25

[Source]

     # File lib/rational.rb, line 124
124:   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
133:     else
134:       x, y = a.coerce(self)
135:       x + y
136:     end
137:   end

Returns the difference of this value and a. subtracted.

Examples:

  r = Rational(3,4)    # -> Rational(3,4)
  r - 1                # -> Rational(-1,4)
  r - 0.5              # -> 0.25

[Source]

     # File lib/rational.rb, line 148
148:   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
157:     else
158:       x, y = a.coerce(self)
159:       x - y
160:     end
161:   end

Returns the quotient of this value and a.

  r = Rational(3,4)    # -> Rational(3,4)
  r / 2                # -> Rational(3,8)
  r / 2.0              # -> 0.375
  r / Rational(1,2)    # -> Rational(3,2)

[Source]

     # File lib/rational.rb, line 195
195:   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)
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
205:     else
206:       x, y = a.coerce(self)
207:       x / y
208:     end
209:   end

Standard comparison operator.

[Source]

     # File lib/rational.rb, line 309
309:   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
328:     else
329:       return nil
330:     end
331:   end

Returns true iff this value is numerically equal to other.

But beware:

  Rational(1,2) == Rational(4,8)          # -> true
  Rational(1,2) == Rational.new!(4,8)     # -> false

Don‘t use Rational.new!

[Source]

     # File lib/rational.rb, line 294
294:   def == (other)
295:     if other.kind_of?(Rational)
296:       @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
301:     else
302:       other == self
303:     end
304:   end

Returns the absolute value.

[Source]

     # File lib/rational.rb, line 277
277:   def abs
278:     if @numerator > 0
279:       self
280:     else
281:       Rational.new!(-@numerator, @denominator)
282:     end
283:   end

[Source]

     # File lib/rational.rb, line 360
360:   def ceil()
361:     -((-@numerator).div(@denominator))
362:   end

[Source]

     # File lib/rational.rb, line 333
333:   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
338:     else
339:       super
340:     end
341:   end

[Source]

     # File lib/rational.rb, line 243
243:   def div(other)
244:     (self / other).floor
245:   end

Returns the quotient and remainder.

Examples:

  r = Rational(7,4)        # -> Rational(7,4)
  r.divmod Rational(1,2)   # -> [3, Rational(1,4)]

[Source]

     # File lib/rational.rb, line 269
269:   def divmod(other)
270:     value = (self / other).floor
271:     return value, self - other * value
272:   end

Converts the rational to an Integer. Not the nearest integer, the truncated integer. Study the following example carefully:

  Rational(+7,4).to_i             # -> 1
  Rational(-7,4).to_i             # -> -1
  (-1.75).to_i                    # -> -1

In other words:

  Rational(-7,4) == -1.75                 # -> true
  Rational(-7,4).to_i == (-1.75).to_i     # -> true

[Source]

     # File lib/rational.rb, line 356
356:   def floor()
357:     @numerator.div(@denominator)
358:   end

Returns a hash code for the object.

[Source]

     # File lib/rational.rb, line 427
427:   def hash
428:     @numerator.hash ^ @denominator.hash
429:   end

[Source]

     # File lib/mathn.rb, line 120
120:   def inspect
121:     format "%s/%s", numerator.inspect, denominator.inspect
122:   end

Returns a reconstructable string representation:

  Rational(5,8).inspect     # -> "Rational(5, 8)"

[Source]

     # File lib/rational.rb, line 420
420:   def inspect
421:     sprintf("Rational(%s, %s)", @numerator.inspect, @denominator.inspect)
422:   end

[Source]

     # File lib/mathn.rb, line 187
187:   def power2(other)
188:     if other.kind_of?(Rational)
189:       if self < 0
190:         return Complex(self, 0) ** other
191:       elsif other == 0
192:         return Rational(1,1)
193:       elsif self == 0
194:         return Rational(0,1)
195:       elsif self == 1
196:         return Rational(1,1)
197:       end
198:       
199:       dem = nil
200:       x = self.denominator.to_f.to_i
201:       neard = self.denominator.to_f ** (1.0/other.denominator.to_f)
202:       loop do
203:         if (neard**other.denominator == self.denominator)
204:           dem = neaed
205:           break
206:         end
207:       end
208:       nearn = self.numerator.to_f ** (1.0/other.denominator.to_f)
209:       Rational(num,den)
210:       
211:     elsif other.kind_of?(Integer)
212:       if other > 0
213:         num = numerator ** other
214:         den = denominator ** other
215:       elsif other < 0
216:         num = denominator ** -other
217:         den = numerator ** -other
218:       elsif other == 0
219:         num = 1
220:         den = 1
221:       end
222:       Rational.new!(num, den)
223:     elsif other.kind_of?(Float)
224:       Float(self) ** other
225:     else
226:       x , y = other.coerce(self)
227:       x ** y
228:     end
229:   end

[Source]

     # File lib/rational.rb, line 373
373:   def round()
374:     if @numerator < 0
375:       num = -@numerator
376:       num = num * 2 + @denominator
377:       den = @denominator * 2
378:       -(num.div(den))
379:     else
380:       num = @numerator * 2 + @denominator
381:       den = @denominator * 2
382:       num.div(den)
383:     end
384:   end

Converts the rational to a Float.

[Source]

     # File lib/rational.rb, line 389
389:   def to_f
390:     @numerator.fdiv(@denominator)
391:   end
to_i()

Alias for truncate

Returns self.

[Source]

     # File lib/rational.rb, line 411
411:   def to_r
412:     self
413:   end

Returns a string representation of the rational number.

Example:

  Rational(3,4).to_s          #  "3/4"
  Rational(8).to_s            #  "8"

[Source]

     # File lib/rational.rb, line 400
400:   def to_s
401:     if @denominator == 1
402:       @numerator.to_s
403:     else
404:       @numerator.to_s+"/"+@denominator.to_s
405:     end
406:   end

[Source]

     # File lib/rational.rb, line 364
364:   def truncate()
365:     if @numerator < 0
366:       return -((-@numerator).div(@denominator))
367:     end
368:     @numerator.div(@denominator)
369:   end

[Validate]