From 7514584b706134864eec1ee8c5732c458b4634ab Mon Sep 17 00:00:00 2001 From: matz Date: Tue, 25 Oct 2005 06:38:26 +0000 Subject: * lib/rational.rb: applied documentation patch from Gavin Sinclair . [ruby-core:06364] * lib/irb.rb (IRB::Irb::eval_input): handle prompts with newlines in irb auto-indentation mode. [ruby-core:06358] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@9464 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/.document | 1 + lib/irb.rb | 2 +- lib/rational.rb | 318 +++++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 250 insertions(+), 71 deletions(-) (limited to 'lib') diff --git a/lib/.document b/lib/.document index 3cb3c859e1..ea9dc9941a 100644 --- a/lib/.document +++ b/lib/.document @@ -25,6 +25,7 @@ matrix.rb observer.rb optionparser.rb pathname.rb +rational.rb set.rb shellwords.rb singleton.rb diff --git a/lib/irb.rb b/lib/irb.rb index 5cacbf859e..1fb4397e68 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -119,7 +119,7 @@ module IRB end if @context.auto_indent_mode unless ltype - ind = prompt(@context.prompt_i, ltype, indent, line_no).size + + ind = prompt(@context.prompt_i, ltype, indent, line_no)[/.*\z/].size + indent * 2 - p.size ind += 2 if continue @context.io.prompt = p + " " * ind if ind > 0 diff --git a/lib/rational.rb b/lib/rational.rb index 2019363ac6..3f15cfafa8 100644 --- a/lib/rational.rb +++ b/lib/rational.rb @@ -1,41 +1,33 @@ # -# rational.rb - -# $Release Version: 0.5 $ -# $Revision: 1.7 $ -# $Date: 1999/08/24 12:49:28 $ -# by Keiju ISHITSUKA(SHL Japan Inc.) +# rational.rb - +# $Release Version: 0.5 $ +# $Revision: 1.7 $ +# $Date: 1999/08/24 12:49:28 $ +# by Keiju ISHITSUKA(SHL Japan Inc.) # -# -- -# Usage: -# class Rational < Numeric -# (include Comparable) +# Documentation by Kevin Jackson and Gavin Sinclair. +# +# When you require 'rational', all interactions between numbers +# potentially return a rational result. For example: # -# Rational(a, b) --> a/b +# 1.quo(2) # -> 0.5 +# require 'rational' +# 1.quo(2) # -> Rational(1,2) +# +# See Rational for full documentation. # -# Rational::+ -# Rational::- -# Rational::* -# Rational::/ -# Rational::** -# Rational::% -# Rational::divmod -# Rational::abs -# Rational::<=> -# Rational::to_i -# Rational::to_f -# Rational::to_s + + # -# Integer::gcd -# Integer::lcm -# Integer::gcdlcm -# Integer::to_r +# Creates a Rational number (i.e. a fraction). +a+ and +b+ should be Integers: +# +# Rational(1,3) # -> 1/3 # -# Fixnum::** -# Fixnum::quo -# Bignum::** -# Bignum::quo +# Note: trying to construct a Rational with floating point or real values +# produces errors: +# +# Rational(1.1, 2.3) # -> NoMethodError # - def Rational(a, b = 1) if a.kind_of?(Rational) && b == 1 a @@ -43,10 +35,39 @@ def Rational(a, b = 1) Rational.reduce(a, b) end end - + +# +# 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. (http://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 +# class Rational < Numeric @RCS_ID='-$Id: rational.rb,v 1.7 1999/08/24 12:49:28 keiju Exp keiju $-' + # + # Reduces the given numerator and denominator to their lowest terms. Use + # Rational() instead. + # def Rational.reduce(num, den = 1) raise ZeroDivisionError, "denominator is zero" if den == 0 @@ -63,13 +84,21 @@ class Rational < Numeric new!(num, den) end 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. + # def Rational.new!(num, den = 1) new(num, den) end private_class_method :new + # + # This method is actually private. + # def initialize(num, den) if den < 0 num = -num @@ -83,7 +112,15 @@ class Rational < Numeric @denominator = den.to_i end 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 + # def + (a) if a.kind_of?(Rational) num = @numerator * a.denominator @@ -98,7 +135,16 @@ class Rational < Numeric x + y end 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 + # def - (a) if a.kind_of?(Rational) num = @numerator * a.denominator @@ -113,7 +159,17 @@ class Rational < Numeric x - y end 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) + # def * (a) if a.kind_of?(Rational) num = @numerator * a.numerator @@ -128,7 +184,14 @@ class Rational < Numeric x * y end 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) + # def / (a) if a.kind_of?(Rational) num = @numerator * a.denominator @@ -144,7 +207,16 @@ class Rational < Numeric x / y end 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 + # def ** (other) if other.kind_of?(Rational) Float(self) ** other @@ -167,17 +239,37 @@ class Rational < Numeric x ** y end 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 + # def % (other) value = (self / other).to_i return self - other * value end - + + # + # Returns the quotient _and_ remainder. + # + # Examples: + # r = Rational(7,4) # -> Rational(7,4) + # r.divmod Rational(1,2) # -> [3, Rational(1,4)] + # def divmod(other) value = (self / other).to_i return value, self - other * value end - + + # + # Returns the absolute value. + # def abs if @numerator > 0 Rational.new!(@numerator, @denominator) @@ -186,6 +278,15 @@ class Rational < Numeric end 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! + # def == (other) if other.kind_of?(Rational) @numerator == other.numerator and @denominator == other.denominator @@ -198,6 +299,9 @@ class Rational < Numeric end end + # + # Standard comparison operator. + # def <=> (other) if other.kind_of?(Rational) num = @numerator * other.denominator @@ -232,14 +336,35 @@ class Rational < Numeric end 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 # -> -2 + # (-1.75).to_i # -> -1 + # + # In other words: + # Rational(-7,4) == -1.75 # -> true + # Rational(-7,4).to_i == (-1.75).to_i # false + # def to_i Integer(@numerator.div(@denominator)) end - + + # + # Converts the rational to a Float. + # def to_f @numerator.to_f/@denominator.to_f end - + + # + # Returns a string representation of the rational number. + # + # Example: + # Rational(3,4).to_s # "3/4" + # Rational(8).to_s # "8" + # def to_s if @denominator == 1 @numerator.to_s @@ -247,38 +372,69 @@ class Rational < Numeric @numerator.to_s+"/"+@denominator.to_s end end - + + # + # Returns +self+. + # def to_r self end - + + # + # Returns a reconstructable string representation: + # + # Rational(5,8).inspect # -> "Rational(5, 8)" + # def inspect sprintf("Rational(%s, %s)", @numerator.inspect, @denominator.inspect) end - + + # + # Returns a hash code for the object. + # def hash @numerator.hash ^ @denominator.hash end - + attr :numerator attr :denominator - + private :initialize end class Integer + # + # In an integer, the value _is_ the numerator of its rational equivalent. + # Therefore, this method returns +self+. + # def numerator self end - + + # + # In an integer, the denominator is 1. Therefore, this method returns 1. + # def denominator 1 end - + + # + # Returns a Rational representation of this integer. + # def to_r Rational(self, 1) end - + + # + # Returns the greatest common denominator of the two numbers (+self+ + # and +n+). + # + # Examples: + # 72.gcd 168 # -> 24 + # 19.gcd 36 # -> 1 + # + # The result is positive, no matter the sign of the arguments. + # def gcd(n) m = self.abs n = n.abs @@ -298,13 +454,13 @@ class Integer end m << b end - + def gcd2(int) a = self.abs b = int.abs - + a, b = b, a if a < b - + while b != 0 void, a = a.divmod(b) a, b = b, a @@ -312,29 +468,49 @@ class Integer return a end - def lcm(int) - a = self.abs - b = int.abs - gcd = a.gcd(b) - (a.div(gcd)) * b + # + # Returns the lowest common multiple (LCM) of the two arguments + # (+self+ and +other+). + # + # Examples: + # 6.lcm 7 # -> 42 + # 6.lcm 9 # -> 18 + # + def lcm(other) + if self.zero? or other.zero? + 0 + else + (self.div(self.gcd(other)) * other).abs + end end - - def gcdlcm(int) - a = self.abs - b = int.abs - gcd = a.gcd(b) - return gcd, (a.div(gcd)) * b + + # + # Returns the GCD _and_ the LCM (see #gcd and #lcm) of the two arguments + # (+self+ and +other+). This is more efficient than calculating them + # separately. + # + # Example: + # 6.gcdlcm 9 # -> [3, 18] + # + def gcdlcm(other) + gcd = self.gcd(other) + if self.zero? or other.zero? + [gcd, 0] + else + [gcd, (self.div(gcd) * other).abs] + end end - end class Fixnum undef quo + # If Rational is defined, returns a Rational number instead of a Fixnum. def quo(other) Rational.new!(self,1) / other end alias rdiv quo - + + # Returns a Rational number if the result is in fact rational (i.e. +other+ < 0). def rpower (other) if other >= 0 self.power!(other) @@ -344,7 +520,7 @@ class Fixnum end unless defined? 1.power! - alias power! ** + alias power! ** alias ** rpower end end @@ -355,11 +531,13 @@ class Bignum end undef quo + # If Rational is defined, returns a Rational number instead of a Bignum. def quo(other) Rational.new!(self,1) / other end alias rdiv quo - + + # Returns a Rational number if the result is in fact rational (i.e. +other+ < 0). def rpower (other) if other >= 0 self.power!(other) @@ -367,7 +545,7 @@ class Bignum Rational.new!(self, 1)**other end end - + unless defined? Complex alias ** rpower end -- cgit v1.2.3