を作りました。
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()
)ぐらいしか無かったので自作しました。需要ないんですかね。
動かないとか仕様が気に食わないとか機能追加しろとか命名が気に入らないとかあったらコメントください。