やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

組込ライブラリ(Numeric)

 数を表すクラス。

成果物

情報源

Numeric

数値を表す抽象クラスです。Integer や Float などの数値クラスは Numeric のサブクラスとして実装されています。

 あれ? Rubyって抽象クラス(abstract class)は存在しないってどこかに書いてなかったっけ?

演算や比較を行うメソッド(+, -, , /, <=>)は Numeric のサブクラスで定義されます。Numeric で定義されているメソッドは、サブクラスで提供されているメソッド (+, -, , /, %) を利用して定義されるものがほとんどです。つまり Numeric で定義されているメソッドは、Numeric のサブクラスとして新たに数値クラスを定義した時に、演算メソッド(+, -, *, /, %, <=>, coerce)だけを定義すれば、数値クラスのそのほかのメソッドが適切に定義されることを意図して提供されています。 

 よくわからんが、Numericを継承して何らかの数値型を作ろうとするときは適切に+メソッドなどを実装しなければならないということか? Numericには適切な実装がないと? だから抽象クラスと呼んだのかな? たとえばRustのようにi8,i16,u8のような型を作ろうとするとき、それぞれに重複する演算コードを実装せねばならないのかな? 面倒そう。まあそんなことしないと思うけど。

+@, -@ は単項演算子 +, - を表しメソッド定義などではこの記法を利用します。

 この単項演算子だけ特殊で@がつくっぽい。

効率のため Numeric のメソッドと同じメソッドがサブクラスで再定義されている場合があります。

 たぶんancestorsでメソッドを探すときの効率の話なのだろう。末端の子孫ほど優先度が高いため早く見つけられるから、わざわざ同じ内容でもサブクラスに実装しているってことなんだと思う。そんな些細な話、べつに知らなくてもいいと思うけど。

Numeric#coerce メソッドを使うことによって異なる数値クラス間で演算を行うこともできます。

 他言語ではダウンキャストやアップキャストをして型をあわせてから演算すると思うけど。

数値関連のメソッドを実際に定義しているクラス一覧

ほとんどの数値関連のメソッドはサブクラスで再定義されています。これは、効率のためであったり上位抽象クラスで実装を定義することができなかったりするためです。以下の表は 2.4.2 での一覧です。実際にどのメソッドがどのクラスに定義されているかはそれぞれのクラスを参照してください。

=> ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-darwin15]
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
                       % |     o          o          o          -          -
                       & |     -          o          -          -          -
                       * |     -          o          o          o          o
                      ** |     -          o          o          o          o
                       + |     -          o          o          o          o
                      +@ |     o          -          -          -          -
                       - |     -          o          o          o          o
                      -@ |     o          o          o          o          o
                       / |     -          o          o          o          o
                       < |     -          o          o          -          -
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
                      << |     -          o          -          -          -
                      <= |     -          o          o          -          -
                     <=> |     o          o          o          o          -
                      == |     -          o          o          o          o
                     === |     -          o          o          -          -
                       > |     -          o          o          -          -
                      >= |     -          o          o          -          -
                      >> |     -          o          -          -          -
                      [] |     -          o          -          -          -
                       ^ |     -          o          -          -          -
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
                     abs |     o          o          o          o          o
                    abs2 |     o          -          -          -          o
                   angle |     o          -          o          -          o
                     arg |     o          -          o          -          o
              bit_length |     -          o          -          -          -
                    ceil |     o          o          o          o          -
                     chr |     -          o          -          -          -
                  coerce |     o          o          o          o          o
                    conj |     o          -          -          -          o
               conjugate |     o          -          -          -          o
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
             denominator |     o          o          o          o          o
                  digits |     -          o          -          -          -
                     div |     o          o          -          -          -
                  divmod |     o          o          o          -          -
                  downto |     -          o          -          -          -
                    eql? |     o          -          o          -          o
                   even? |     -          o          -          -          -
                    fdiv |     o          o          o          o          o
                 finite? |     o          -          o          -          o
                   floor |     o          o          o          o          -
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
                     gcd |     -          o          -          -          -
                  gcdlcm |     -          o          -          -          -
                    hash |     -          -          o          o          o
                       i |     o          -          -          -          -
                    imag |     o          -          -          -          o
               imaginary |     o          -          -          -          o
               infinite? |     o          -          o          -          o
                 inspect |     -          o          o          o          o
                integer? |     o          o          -          -          -
                     lcm |     -          o          -          -          -
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
               magnitude |     o          o          o          o          o
                  modulo |     o          o          o          -          -
                    nan? |     -          -          o          -          -
               negative? |     o          -          o          o          -
                    next |     -          o          -          -          -
              next_float |     -          -          o          -          -
                nonzero? |     o          -          -          -          -
               numerator |     o          o          o          o          o
                    odd? |     -          o          -          -          -
                     ord |     -          o          -          -          -
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
                   phase |     o          -          o          -          o
                   polar |     o          -          -          -          o
               positive? |     o          -          o          o          -
                    pred |     -          o          -          -          -
              prev_float |     -          -          o          -          -
                     quo |     o          -          o          o          o
             rationalize |     -          o          o          o          o
                    real |     o          -          -          -          o
                   real? |     o          -          -          -          o
                    rect |     o          -          -          -          o
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
             rectangular |     o          -          -          -          o
               remainder |     o          o          -          -          -
                   round |     o          o          o          o          -
  singleton_method_added |     o          -          -          -          -
                    size |     -          o          -          -          -
                    step |     o          -          -          -          -
                    succ |     -          o          -          -          -
                   times |     -          o          -          -          -
                    to_c |     o          -          -          -          o
                    to_f |     -          o          o          o          o
                            Numeric    Integer     Float     Rational   Complex
 --------------------------------------------------------------------------------
                    to_i |     -          o          o          o          o
                  to_int |     o          o          o          -          -
                    to_r |     -          o          o          o          o
                    to_s |     -          o          o          o          o
                truncate |     o          o          o          o          -
                    upto |     -          o          -          -          -
                   zero? |     o          -          o          -          -
                       | |     -          o          -          -          -
                       ~ |     -          o          -          -          -

丸めメソッドの動作一覧

Numeric#ceil, Numeric#floor, Numeric#round, Numeric#truncate のふるまいの違いの表です。左の実数に対して各メソッドを呼ぶと表のような数を返します。

      |       ceil      floor      round   truncate
----------------------------------------------------
  1.9 |          2          1          2          1
  1.1 |          2          1          1          1
 -1.1 |         -1         -2         -1         -1
 -1.9 |         -1         -2         -2         -1

 負数のときの切り捨て(floor)って負数側に寄るんだね。知らんかった。負数を含めた本当の意味での切り捨てはtruncateのほうか。

丸めメソッドの拡張例

切上げはceil, floor を使用して以下のように定義できます。

if n > 0 then
  n.ceil
else
  n.floor
end

 負数を含めた切り捨てはtrancateだけど、負数を含めた切り上げメソッドは存在しない。それがしたければ上記コードで対応しろってことか。

また、任意桁の切上げ、切捨て、四捨五入を行うメソッドは以下のように定義できます。

class Numeric
  def roundup(d=0)
    x = 10**d
    if self > 0
      self.quo(x).ceil * x
    else
      self.quo(x).floor * x
    end
  end

  def rounddown(d=0)
    x = 10**d
    if self < 0
      self.quo(x).ceil * x
    else
      self.quo(x).floor * x
    end
  end

  def roundoff(d=0)
    x = 10**d
    if self < 0
      (self.quo(x) - 0.5).ceil * x
    else
      (self.quo(x) + 0.5).floor * x
    end
  end
end

 需要があると思うなら最初から実装してくれたらいいのに。

メンバ抜粋

インスタンスメソッド

% +@ -@ <=> abs abs2 angle arg ceil coerce conj conjugate 
denominator div divmod eql? fdiv finite? floor i imag imaginary 
infinite? integer? magnitude modulo negative? nonzero? 
numerator phase polar positive? quo real real? rect rectangular 
remainder round step to_c to_int truncate zero?
記号 演算 メソッド
% 剰余 modulo,divmod,remainder
+ 加算
- 減算
* 乗算
/ 除算 div,divmod,quo
<=> 三方比較演算
絶対値 abs,magnitude
メソッド 概要
negative? ゼロ未満のときtrue、それ以外のときfalseを返す
positive? ゼロより大きいときtrue、それ以外のときfalseを返す
nonezero? ゼロのときnil、それ以外のときselfを返す
zero? ゼロのときtrue、それ以外のときfalseを返す
メソッド 概要
ceil 切り上げ。self以上な整数のうち最小値を返す。
floor 切り捨て。self以下な整数のうち最大値を返す。
round 四捨五入。偶数丸めでない。
trancate 0selfの間で最も近い整数を返す
p 10 % 3          #=> 1
p 10.modulo(3)    #=> 1
p 10.divmod(3)    #=> [3, 1]
p 10.remainder(3) #=> 1

p 10 / 3    #=> 3
p 10.div(3) #=> 3
p 10.quo(3) #=> (10/3)

 除算は/divにより商を整数で得られる。quoで近似値?を得る。他言語なら浮動小数点になるところだが(10/3)という表示から、もっと正確な値を保持していると思われる。

対象環境

$ uname -a
Linux raspberrypi 5.10.52-v7l+ #1441 SMP Tue Aug 3 18:11:56 BST 2021 armv7l GNU/Linux