Rubyでの小数点以下の丸め方と参考書籍

昨日のエントリーで、小数点以下の丸めをうまく制御できなくて、TDDがうまくいかなくて悲しい、ということがあったので、今日は値を特定の小数点以下の桁数で丸めるコードを書いてみます。

デリバティブの計算などでは、金額の精度が非常に重要になります。たとえばDFの小数点以下8桁の数字が違っても、想定元本が100億円とかであればかなりの金額の差になってしまいます。今日書くのは、そこまで厳密なものではないですが、まずは腕慣らしということで。

まず、TDDなのでテストです。util.rbと言うファイルで、Numericクラスをround_toと言うメソッドで拡張します。
round_toは、小数点以下の有効桁数を引数に取って、それ以下を丸めます。

util_test.rb

require 'test/unit'
require 'util'
class UtilTest < Test::Unit::TestCase
  def test_round_by
    assert_equal(1, 0.5.round_to(0))
    assert_equal("0.6", 0.55.round_to(1).to_s)
    assert_equal("0.99009901", 0.99009900990099.round_to(8).to_s)
  end
end

これが通るように、実装します。

util.rb

class Numeric
  def round_to(valid_digit)
    powered = self * (10 ** valid_digit)
    powered.round * (10 ** -valid_digit)
  end
end

テスト実行。

$ ruby util_test.rb
Loaded suite util_test
Started
.
Finished in 0.000813 seconds.

1 tests, 3 assertions, 0 failures, 0 errors

通りましたね。
少しソースの解説をすると、桁数を有効桁数分上げて、その時点で小数の部分を第1位で四捨五入しています。その後、有効桁数分下げると、小数点以下有効桁数分残ります。

この方法は、以下の定番書籍を参考にしました。

Rubyレシピブック 第2版 268の技

Rubyレシピブック 第2版 268の技

この書籍の著者の一人、青木さんは、Haskell本の著者でもありますね。

青木さんの著作では、タイトルは若干損している気がしますが、(→Webで十分だと思われそう)この本もオススメです。