2011年10月28日

Ruby on Rails 小数の表示桁数指定 切り捨て

小数桁数指定の切り捨て表示


railsで1.99999などを1.99で表示などが何気に面倒だったので表示方法を記載します。

環境


ruby1.9.1
rails2.3.11

今回なぜ切り捨て表示を使用としたか


AとBという値があり双方を比較する処理があります。
Aは自由に設定できる数値で、Bは自動で算出されるデータとなります。
AとBを比較した結果Bが大きければ特定の処理を行うというものです。

何が起きたかというと、
B>=Aなのに処理が実行されないという現象が起きました。
(BはDBに保存されておりviewで表示している)

原因


原因はview側で表示するときに
sprintf("%0.2f", 数値)

としており、小数第3位の値が四捨五入されてしまっているため表示している値が異なりviewと実際の処理に誤差が生じてしまいました。

例:
A=0.05
B(DB)=0.0453251
B(view)=0.05


解決方法


実際の処理が間違っているわけではないのでviewがわの表示を切り捨てで表示すればよいだけです。

この切り捨てで小数位置指定がなにげに面倒でした。

・floor
> hoge=1.9999
=> 1.9999
>> hoge.floor
=> 1
>> hoge.floor(2)
ArgumentError: wrong number of arguments(1 for 0)
from (irb):8:in `floor'
from (irb):8
from /home/search/ruby/bin/irb:12:in `<main>'

整数を返すので☓
これに引数与えれば小数第?位を表示とかしてくれたら楽だったんだが。

・s
> hoge=1.9999
=> 1.9999
>> sprintf("%0.4s", hoge)
=> "1.99"
> hoge=9.27092e-05
=> 9.27092e-05
>> sprintf("%0.4s", hoge)
=> "9.27"
>> sprintf("%0.2f", hoge)
=> "0.00"
>> sprintf("%0.10f", hoge)
=> "0.0000927092"

sprintfのsは四捨五入、これでうまく行きそうでしたが、
「9.27092e-05」こいつのせいで☓
これはなにか?というと、小数の桁数が大きすぎると「e-05」で小数点の位置を示します。
実際の数値は「0.0000927092」なので「e-05」は「0.0000」を前につけるようになります。
sでこれを処理しようとすると上記の通り「9.27」になってしまうので☓となります。
惜しい


BigDecimal
あんまり詳しくは知りませんが、可変長浮動小数点計算機能ライブラリです。
> hoge=9.27092e-05
=> 9.27092e-05
>> BigDecimal("#{hoge}")
=> #<BigDecimal:7cd07f8,'0.927092E-4',18(18)>
>> BigDecimal("#{hoge}").floor(2)
=> #<BigDecimal:7cc5e70,'0.0',9(36)>
>> sprintf("%0.2f",BigDecimal("#{hoge}").floor(2))
=> "0.00"
>> sprintf("%0.7f",BigDecimal("#{hoge}").floor(7))
=> "0.0000927"
>> sprintf("%0.6f",BigDecimal("#{hoge}").floor(6))
=> "0.000092"

まずBigDecimalはStringしかダメなので"#{}"これで囲ってあげます。
次に、BigDecimalを使用するとfloorで小数第何位まで表示するか指定可能となります。
そのままだと「#<BigDecimal:7cc5e70,'0.0',9(36)>」こんな表示なので
sprintfのfで表示を整えてあげると完成です。
fは四捨五入ですが、floorで切り捨てているので問題なし。
posted by RicK at 19:04| Comment(0) | TrackBack(0) | 日記