やりたい事
floor.rb
12.3456 => 12.34
255/13 => 19.61
こんな処理をしたい場合。
すぐに思いつくのは、floor関数。
Class: Float (Ruby 2.1.5) #floor
floor.rb
1.2.floor #=> 1
2.0.floor #=> 2
(-1.2).floor #=> -2
(-2.0).floor #=> -2
残念ながら、float型はfloor関数に引数(小数点以下指定)を指定する事ができません。
これは、浮動小数点問題があるからなのでしょうか。。。(?)
仕方ないので別の方法を探します。
BigDecimal
floor.rb
BigDecimal("1.23456").floor # => 1
BigDecimal("-1.23456").floor # => -2
BigDecimal("1.23456").floor(4).to_f # => 1.2345
BigDecimal("15.23456").floor(-1).to_f # => 10.0
BigDecimal型にもfloor関数があり、こちらのfloor関数は引数に小数点以下を指定可能です。
これを使いましょう。
注意点
さきほどのやりたい事を、やってみます
floor.rb
[6] pry(main)> BigDecimal(12.3456).floor(2)
ArgumentError: can't omit precision for a Float.
from (pry):5:in `BigDecimal'
float型をそのまま引数で渡すとエラーとなってしまいます。
これはおそらく、float型を渡してる時点ですでに、浮動小数点問題により誤差が生じて正確な値じゃなくなっちゃうからだと思われます。
BigDecimalの引数にはStringを渡しましょう。
floor.rb
[7] pry(main)> BigDecimal('12.3456').floor(2)
=> #<BigDecimal:7f8cbf78fe30,'0.1234E2',18(27)>
[8] pry(main)> BigDecimal('12.3456').floor(2).to_f
=> 12.34
どうせStringを渡すのであれば、String/Integer/Floatなどには#to_d
が用意されているので、これを使うともっとシンプルになりそうです
Class: String (Ruby 1.9.3)
floor.rb
[9] pry(main)> '12.3456'.to_d.floor(2)
=> #<BigDecimal:7f8cbf7e2428,'0.1234E2',18(27)>
[10] pry(main)> '12.3456'.to_d.floor(2).to_f
=> 12.34
もう一つのやりたい事もやってみます。
floor.rb
[35] pry(main)> (255.to_d/13.to_d).floor(2).to_f
=> 19.61
参考
[Ruby]消費税計算にはBigDecimalを使いましょう - Qiita
Class: String (Ruby 1.9.3)
class BigDecimal
小数第2位以下の切り捨て - ayaketanのプログラミング勉強日記