Ruby

数値を(基準値の倍数で|有効桁数で)丸めるgem

More than 3 years have passed since last update.

作りました

rubyならこのくらい組み込まれてても良さそうですが、無いのが意外です。


インストール

$ gem install pretty_round


使い方

require "pretty_round"

x = 123.456

# 指定した精度で丸める
x.roundup #=> 124
x.rounddown(2) #=> 123.45

# 基準値の倍数で丸める
# いわゆるExcelのMROUND()関数です。
x.mceil(50) #=> 150
x.mfloor(25) #=> 100
x.mroundup(2) #=> 124
x.mrounddown(0.3) #=> 123.3
x.mround(9.87) #=> 128.31

# 有効桁数で丸める
# IT界隈ではあまり見かけない丸め方ですが個人的によく使うのでgemに含めました。
x.sceil(1) #=> 200
x.sfloor(2) #=> 120
x.sroundup(3) #=> 124
x.srounddown(4) #=> 123.4
x.sround(5) #=> 123.46


丸め方向



  • #*ceil, #*floorとなっているものは、が大きい方、小さい方に丸めます。ruby組み込みの#ceil#floorと同じ挙動です。


  • #*roundup, #*rounddownとなっているものは、絶対値が大きい方、小さい方に丸めます。


  • #*roundとなっているものは絶対値を四捨五入します。なお偶数丸めではありません。ruby組み込みの#roundと同じ挙動です。


  • #*truncate#*rounddownと同じです。

一覧にすると以下のようになります。対比のため、ruby組み込みのメソッドも含めました。

縦がメソッド、横がレシーバです。

              |  1.9  1.1 -1.1 -1.9

-----------------------------------
.ceil | 2 2 -1 -1 (ruby組み込み)
.floor | 1 1 -2 -2 (ruby組み込み)
.roundup | 2 2 -2 -2
.rounddown | 1 1 -1 -1
.round | 2 1 -1 -2 (ruby組み込み)
.truncate | 1 1 -1 -1 (ruby組み込み)
.mceil(1) | 2 2 -1 -1
.mfloor(1) | 1 1 -2 -2
.mroundup(1) | 2 2 -2 -2
.mrounddown(1)| 1 1 -1 -1
.mround(1) | 2 1 -1 -2
.mtruncate(1) | 1 1 -1 -1
.sceil(1) | 2 2 -1 -1
.sfloor(1) | 1 1 -2 -2
.sroundup(1) | 2 2 -2 -2
.srounddown(1)| 1 1 -1 -1
.sround(1) | 2 1 -1 -2
.struncate(1) | 1 1 -1 -1


既知のバグ

ruby 2.2.3で確認しています。

何か解決策があったらご教示ください…。


Floatの精度

1.2.mrounddown(0.1) #=> 1.1

ファッ!

もちろん1.2になるのが正解です。

なぜこうなるのかといえば、

1.2.divmod(0.1) #=> [11, 0.0999999999999999]

になるからです。回避策としてはRational使いましょう。Floatは信用ならない。

1.2r.mrounddown(0.1r) #=> (6/5)


勝手にRationalになる

0.123.sround(2).class #=> Rational

別に問題無いといえば問題無いのですが。

なぜこうなるのかといえば

(10**(-1)).class #=> Rational

の様にFixnum同士の演算がRationalになる事があるからです。前からこんな仕様でしたっけ?


おわりに

個人的に有効桁数で丸めるメソッドを必要としていたのですが、これがある言語はR(signif())ぐらいしか無かったので自作しました。需要ないんですかね。

動かないとか仕様が気に食わないとか機能追加しろとか命名が気に入らないとかあったらコメントください。