数を表すクラス。
成果物
情報源
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 |
0 〜self の間で最も近い整数を返す |
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)
という表示から、もっと正確な値を保持していると思われる。
対象環境
- Raspbierry pi 4 Model B
- Raspberry Pi OS buster 10.0 2020-08-20 ※
- bash 5.0.3(1)-release
- Ruby 3.0.2
$ uname -a Linux raspberrypi 5.10.52-v7l+ #1441 SMP Tue Aug 3 18:11:56 BST 2021 armv7l GNU/Linux