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
Unify | = | true |
** | -> | power! |
denominator | [R] | |
numerator | [R] |
This method is actually private.
# 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
Reduces the given numerator and denominator to their lowest terms. Use Rational() instead.
# 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
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
# 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)
# 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
# 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
# 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
# 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
# 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)
# 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.
# 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!
# 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.
# 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
# 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
Returns the quotient and remainder.
Examples:
r = Rational(7,4) # -> Rational(7,4) r.divmod Rational(1,2) # -> [3, Rational(1,4)]
# 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
# File lib/rational.rb, line 356 356: def floor() 357: @numerator.div(@denominator) 358: end
# 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)"
# File lib/rational.rb, line 420 420: def inspect 421: sprintf("Rational(%s, %s)", @numerator.inspect, @denominator.inspect) 422: end
# 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
# 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
Returns a string representation of the rational number.
Example:
Rational(3,4).to_s # "3/4" Rational(8).to_s # "8"
# 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