From: Tadayoshi Funaba Date: 2008-02-09T08:06:02+09:00 Subject: [ruby-dev:33662] rational, complex and mathn rational は floor、truncate、ceil、round を定義していません。Numeric のまま提供しています。しかし、Numeric のものは、浮動小数点数に変換して しまうためまともな結果が得られるとは限りません。[ruby-dev:32201] 現状、floor のかわりに to_i をつかって問題がないのは、to_i の定義が floor になっているからです。Float#to_i の定義から、Numeric の to_i は truncate であるべきだと思います。 Complex(1,2).numerator がエラーになります。rational を読んでいるとエラー になりません。 $ ruby19 -r complex -e 'Complex(1,2).numerator' /usr/local/ruby19/lib/ruby/1.9.0/complex.rb:345:in `denominator': undefined method `denominator' for 1:Fixnum (NoMethodError) from /usr/local/ruby19/lib/ruby/1.9.0/complex.rb:352:in `numerator' from -e:1:in `
' Complex#quo が機能しません。普通に整数割りしてしまいます。 $ ruby19 -r complex -e 'p Complex(1,2).quo(2)' Complex(0, 1) $ ruby19 -r complex -r rational -e 'p Complex(1,2).quo(2)' Complex(0, 1) complex では、不要に思えるメソッドが放置してあります。>、>=、<、<=、 between?、floor、ceil、round、truncate など。1.8 では、step、<=> も。 あと、% は意味があるのでしょうか。 mathn で、Rational#inspect を書き換えているが、さすがに余計なお世話の ような気もします。どうしてもしたければ、そういうことは、irb などアプリ ケーション側でやればいいような気がします。 以下修正案。floor、ceil、truncate、round は原さんの rational からパク りました。 Index: lib/rational.rb =================================================================== --- lib/rational.rb (revision 15409) +++ lib/rational.rb (working copy) @@ -238,6 +238,10 @@ end end + def div(other) + (self / other).floor + end + # # Returns the remainder when this value is divided by +other+. # @@ -249,7 +253,7 @@ # r % 0.26 # -> 0.19 # def % (other) - value = (self / other).to_i + value = (self / other).floor return self - other * value end @@ -261,7 +265,7 @@ # r.divmod Rational(1,2) # -> [3, Rational(1,4)] # def divmod(other) - value = (self / other).to_i + value = (self / other).floor return value, self - other * value end @@ -270,7 +274,7 @@ # def abs if @numerator > 0 - Rational.new!(@numerator, @denominator) + self else Rational.new!(-@numerator, @denominator) end @@ -345,10 +349,37 @@ # Rational(-7,4) == -1.75 # -> true # Rational(-7,4).to_i == (-1.75).to_i # false # - def to_i - Integer(@numerator.div(@denominator)) + + def floor() + @numerator.div(@denominator) end + def ceil() + -((-@numerator).div(@denominator)) + end + + def truncate() + if @numerator < 0 + return -((-@numerator).div(@denominator)) + end + @numerator.div(@denominator) + end + + alias_method :to_i, :truncate + + def round() + if @numerator < 0 + num = -@numerator + num = num * 2 + @denominator + den = @denominator * 2 + -(num.div(den)) + else + num = @numerator * 2 + @denominator + den = @denominator * 2 + num.div(den) + end + end + # # Converts the rational to a Float. # @@ -476,10 +507,11 @@ class Fixnum alias quof quo - undef quo - # If Rational is defined, returns a Rational number instead of a Fixnum. + remove_method :quo + + # If Rational is defined, returns a Rational number instead of a Float. def quo(other) - Rational.new!(self,1) / other + Rational.new!(self, 1) / other end alias rdiv quo @@ -488,26 +520,18 @@ if other >= 0 self.power!(other) else - Rational.new!(self,1)**other + Rational.new!(self, 1)**other end end - - unless defined? 1.power! - alias power! ** - alias ** rpower - end end class Bignum - unless defined? Complex - alias power! ** - end + alias quof quo + remove_method :quo - alias quof quo - undef quo - # If Rational is defined, returns a Rational number instead of a Bignum. + # If Rational is defined, returns a Rational number instead of a Float. def quo(other) - Rational.new!(self,1) / other + Rational.new!(self, 1) / other end alias rdiv quo @@ -519,8 +543,15 @@ Rational.new!(self, 1)**other end end +end - unless defined? Complex +unless defined? 1.power! + class Fixnum + alias power! ** alias ** rpower end + class Bignum + alias power! ** + alias ** rpower + end end Index: lib/mathn.rb =================================================================== --- lib/mathn.rb (revision 15409) +++ lib/mathn.rb (working copy) @@ -121,11 +121,6 @@ class Rational Unify = true - remove_method :inspect - def inspect - format "%s/%s", numerator.inspect, denominator.inspect - end - alias power! ** def ** (other) Index: lib/complex.rb =================================================================== --- lib/complex.rb (revision 15409) +++ lib/complex.rb (working copy) @@ -104,6 +104,10 @@ @RCS_ID='-$Id: complex.rb,v 1.3 1998/07/08 10:05:28 keiju Exp keiju $-' undef step + undef <, <=, <=>, >, >= + undef between? + undef divmod, modulo + undef floor, truncate, ceil, round def scalar? false @@ -199,6 +203,10 @@ x/y end end + + def quo(other) + Complex(@real.quo(1), @image.quo(1)) / other + end # # Raise this complex number to the given (real or complex) power. @@ -248,6 +256,8 @@ # # Remainder after division by a real or complex number. # + +=begin def % (other) if other.kind_of?(Complex) Complex(@real % other.real, @image % other.image) @@ -258,7 +268,8 @@ x % y end end - +=end + #-- # def divmod(other) # if other.kind_of?(Complex) @@ -312,8 +323,6 @@ end alias conj conjugate - undef <=> - # # Test for numerical equality (a == a + 0i). # @@ -410,9 +419,35 @@ end +class Integer + unless defined?(1.numerator) # temporal + def numerator() self end + def denominator() 1 end + def gcd(other) + min = self.abs + max = other.abs + while min > 0 + tmp = min + min = max % min + max = tmp + end + max + end + def lcm(other) + if self.zero? or other.zero? + 0 + else + (self.div(self.gcd(other)) * other).abs + end + end + + end + +end + module Math alias sqrt! sqrt alias exp! exp