小林です。

----- Original Message -----
From: "Wakou Aoyama" <wakou / fsinet.or.jp>
Subject: [ruby-math:00304] Re: Float#ceil, Float#floor, Float#round


> 青山です。
こんにちわ。

>
> ええ、標準の Float での話なので、精度については、その程度という前提で
> す。で、BigFloat にも、任意の桁数でまるめるメソッドは無いんですね。計
> 測データの計算などではあると便利そうですが。

確かに....
小数点以下 n 位で四捨五入するには 10 の n-1 乗を掛けて、
それから round して、さらに 10 の n-1 乗で割ればできますが.....
例えば、1.2345678 を小数点以下 5 位で丸めるには

require "BigFloat"
a = BigFloat::new("1.2345678")
n = BigFloat::new("10")
p a = a * n.power(4)
p a.round
p a = a/n

っと思ったらバグが(がーーーーーん)。

# diff bigfloat.c bigfloat.c.old
2054c2054
<    if(a->MaxPrec>n) {
---
>    if(a->MaxPrec >(n + 1)) {
2056c2056
<        (a->frac[n] >= HALF_BASE)) VpRdup(c); /* round up/off */
---
>        (a->frac[n + 1] >= HALF_BASE)) VpRdup(c); /* round up/off */

# 時間ができたら、round に引数を与えて、任意の桁で丸める
# ことができるようにするつもりです。

>
> まあ、もっとも、BigFloat に関しては、なんらかの演算をして、そのついで
> にという手はありますか。と、思いましたが、ちょっと期待した動きと違うよ
> うですね。
>
> require "BigFloat"
> a = BigFloat::new("0.111")
> b = BigFloat::new("0.333")
> p a  # [BigFloat:401f66bc,'0.1110E0',4(8)]
> p b  # [BigFloat:401f6694,'0.3330E0',4(8)]
> p a.div(b,  1)[0]  # [BigFloat:401fe76c,'0.0',4(8)]
> p a.div(b,  2)[0]  # [BigFloat:401fe71c,'0.0',4(8)]
> p a.div(b,  3)[0]  # [BigFloat:401fe6cc,'0.0',4(8)]
> p a.div(b,  4)[0]  # [BigFloat:401fe67c,'0.0',4(8)]
> p a.div(b,  5)[0]  # [BigFloat:401fe62c,'0.3333E0',4(12)]
> p a.div(b,  6)[0]  # [BigFloat:401fe5dc,'0.3333E0',4(12)]
> p a.div(b,  7)[0]  # [BigFloat:401fe58c,'0.3333E0',4(12)]
> p a.div(b,  8)[0]  # [BigFloat:401fe53c,'0.3333E0',4(12)]
> p a.div(b,  9)[0]  # [BigFloat:401fe4ec,'0.33333333E0',8(16)]
> p a.div(b, 10)[0]  # [BigFloat:401fe49c,'0.33333333E0',8(16)]
>
(略)
>
> 結果を見ると、n の扱いがちょっと違うような。
>
これは、32ビットシステムでは10進数4桁毎に区切って内部
計算していることによります。
で、最後の32ビット(10進数4桁)は特別に処理しなければ
いけないのですが、ここをサボっているのがばればれですね。 ^^;;
ただ、利用する側から見ればまったく理不尽なことはジュウジュウ
承知しておりますです。

# 現在の BigFloat の仕様も含めて、そのうち見直すつもりです。
# ご意見お待ちしております。

小林 茂雄
shigeo / tinyforest.gr.jp