1.9.3 (以降) の BigDecimal について

BigDecimal()
$B$G@0?t!“IbF0>.?tE@?t!“M-M}?t$J$I$r<u$1$H$l$k$h$&$K$J$C$F!”(B
$BIbF0>.?tE@?t!“M-M}?t$G$O!”@:EY$N;XDj$,I,?$K$J$C$F$$$k$h$&$G$9!#0lJ}$G!”(B
bigdecimal/util $B$K$"$k(B #to_d
$B$G$O!"$=$&$G$O$J$/!“JQ49$H$$$&LL$G8+$F!“2?(B
$B8N0c$$$,$”$k$N$+!”$I$N$h$&$JH=CG$J$N$+CN$j$?$$$G$9!#(B

$B$"$H!"(BBigDecimal(anInteger) $B$,$"$C$F!"(BInteger#to_d
$B$,$J$$;v$b!#(B

むらたです。

On 2011年7月23日土曜日 at 22:02, Tadayoshi F. wrote:

BigDecimal() で整数、浮動小数点数、有理数などを受けとれるようになって、
浮動小数点数、有理数では、精度の指定が必須になっているようです。一方で、
bigdecimal/util にある #to_d では、そうではなく、変換という面で見て、何
故違いがあるのか、どのような判断なのか知りたいです。

あと、BigDecimal(anInteger) があって、Integer#to_d がない事も。

修正漏れ、つまりバグです。

ご報告ありがとうございます。


Kenta M.
Sent with Sparrow (http://www.sparrowmailapp.com)

$B=$@5O3$l!"$D$^$j%P%0$G$9!#(B

$B$=$N@:EY$N;XDj$r$I$&$9$Y$-$+$OJL$H$7$F!“0JA0$H$OJ}?K$,JQ$C$F$-$F!”<c43(B
ruby $B$N(B Numeric $B$H$7$FIaDL$K$J$m$&$H$7$F$$$k5$G[$r46$8$^$9!#(B

$B$=$&$G$"$k$H$9$l$P!"(B

Integer(Integer(‘1’)) #=> 1
Rational(Rational(‘1’)) #=> (1/1)

1.0.to_f #=> 1.0
Complex(1,2).to_c #=> (1+2i)

$B$H$$$&;v$,$"$k$N$G!"(B

BigDecimal(BigDecimal(‘1’)) # TypeError:
BigDecimal(1).to_d # NoMethodError:

$B$J$I$b5!G=$9$k$h$&$K$J$j$^$9$+$M!#(B

むらたです。

On 2011年7月26日火曜日 at 22:43, Tadayoshi F. wrote:

1.0.to_f #=> 1.0
Complex(1,2).to_c #=> (1+2i)

という事があるので、

BigDecimal(BigDecimal(‘1’)) # TypeError:
BigDecimal(1).to_d # NoMethodError:

なども機能するようになりますかね。

おおお。確かに、この二つの事もすっかり忘れていました。
ありがとうございます。助かりました。


Kenta M.
Sent with Sparrow (http://www.sparrowmailapp.com)

$BJQ49$K$OL@<(E*$J$b$N$H$=$&$G$J$$$b$N$,$"$j$^$9$,!"(B

BigDecimal(Rational(1,3)) # ArgumentError:
Rational(1,3) + BigDecimal(0) #=>
#BigDecimal:9fb65cc,‘0.333333333E0’,9(36)
Rational(1,3) + BigDecimal(‘0’,1000) #=>
#BigDecimal:a319728,‘0.333333333E0’,9(36)

$B8e<T$N>l9g$K@:EY$N;XDj$O$J$$$o$1$G$9$h$M!#(B

$B$=$l$+$i!"$"$k(B to_d $B$,I,?$N0z?t$rMW5a$7!"$^$?$"$k(B to_d
$B$O0z?t$r<u$1$H(B
$B$i$J$$!"$H$$$&$3$H$K$J$k$H!“G$0U$N?tCM$r$H$j$”$($:(B BigDecimal
$B$K$7$?$$(B
$B$H$$$&>l9g$KMxMQ$,Fq$7$/$J$j$^$9!#(B

1.to_d #=> #BigDecimal:9ebcdd8,‘0.1E1’,9(36)
Rational(1,3).to_d # ArgumentError:

Rational(1,3).to_d(10) #=>
#BigDecimal:9edd650,‘0.3333333333E0’,18(45)
1.to_d(10) # ArgumentError:

$B$?$H$($P!"(BRational(1).to_d(10) $B$H$$$&I=8=$O!"(Bmathn
$B$J$7$G$OLdBj$"$j$^$;(B
$B$s$,!"(Bmathn $B$,$"$C$?>l9g$K%(%i!<$K$J$j$^$9!#(B

$B$H$$$&$H$3$m$G!"@:EY$NMW5a$H$=$NM?$($+$?$KAGKQ$K5?Ld$r46$8$^$9!#(B

$B8e<T$N0EL[E*JQ49$K$D$$$F$O!"Aj<j$N(B BigDecimal
$B$K9g$o$;$F@:EY$r7hDj$G$-$^$9!#(B

BigDecimal(Rational(Math::PI),100)
#=> #<BigDecimal:9cd6848,‘0.3141592653 5897931159 9796346854
4185161590 576171875E1’,63(135)>

Rational(Math::PI) + BigDecimal(‘0.’ + ‘0’ * 50 + ‘1’)
#=> #<BigDecimal:9cd8ef4,‘0.3141592650 0000000000 0000000000
0000000000 0000000000 01E1’,63(90)>

$BC1$K7e$,A}$($?$@$1$K8+$($^$9!#(B

$B>o<1E*$K9M$($F1F6A$,>/$J$=$&$JNm$r2C;;$r$9$k$H:GDc8B$N@:EY$K$J$k!"$H$$(B
$B$&$N$G$"$l$P!“L@<(E*$JJQ49$GI,?$K$9$k;v$b$”$^$j0UL#$,$J$$$h$&$J5$$,$7(B
$B$^$9!#(B

むらたです。

On Sunday, July 31, 2011 at 01:02 , Tadayoshi F. wrote:

変換には明示的なものとそうでないものがありますが、

BigDecimal(Rational(1,3)) # ArgumentError:
Rational(1,3) + BigDecimal(0) #=> #BigDecimal:9fb65cc,‘0.333333333E0’,9(36)
Rational(1,3) + BigDecimal(‘0’,1000) #=>
#BigDecimal:a319728,‘0.333333333E0’,9(36)

後者の場合に精度の指定はないわけですよね。

後者の暗黙的変換については、相手の BigDecimal に合わせて精度を決定できます。

それから、ある to_d が必須の引数を要求し、またある to_d は引数を受けと
らない、ということになると、任意の数値をとりあえず BigDecimal にしたい
という場合に利用が難しくなります。

確かにその通りですね。すべての to_d が明示的な精度を受け取れるように修正が必要ですね。
ご指摘ありがとうございます。


Kenta M.
Sent with Sparrow (http://www.sparrowmailapp.com)

$B$@$+$i!“8=;~E@$G@:EY$rI,?$K$9$k$N$O$”$^$j0UL#$,$J$$$s$8$c$J$$$G$9$+$M!#(B
$B:G=E$K$I$&$J$k$N$+H=$i$J$$0J>e!":#2s$N;EMMJQ99$,NI$$$N$+H=CG$G$-$J$$(B
$B$G$9$M!#(B

むらたです。

On Monday, August 1, 2011 at 00:17 , Tadayoshi F. wrote:

だから、現時点で精度を必須にするのはあまり意味がないんじゃないですかね。
最終的にどうなるのか判らない以上、今回の仕様変更が良いのか判断できない
ですね。

1.9.3 の Rational#to_d は精度を必須とする変更を中止しています。


Kenta M.
Sent with Sparrow (http://www.sparrowmailapp.com)

むらたです。

On Sunday, July 31, 2011 at 22:51 , Tadayoshi F. wrote:

常識的に考えて影響が少なそうな零を加算をすると最低限の精度になる、とい
うのであれば、明示的な変換で必須にする事もあまり意味がないような気がし
ます。

現在の bigdecimal は精度の仕様に問題がある事を前提に以下の話を読んで下さい。

小数点以下の桁数 (確度; accuracy) と、数値の有効桁数 (精度; precision) は事なる概念です。
coerce が使うのは精度です。精度には、先頭の0の列を桁数には含みません。

以下のように、長い有効数字を持つ BigDecimal を用いて coerce すると、
Rational から変換された BigDecimal の有効数字が coerce のレシーバが持つ
有効数字に対応している事が分かると思います。

BigDecimal(“0.” + “1”*50+“1”).coerce(Rational(Math::PI))
#=> [#<BigDecimal:7f9ea387c0c8,‘0.3141592653 5897931159 9796346854
4185161590 576171875E1’,63(81)>,
#<BigDecimal:7f9ea387c1e0,‘0.1111111111 1111111111 1111111111 1111111111
1111111111 1E0’,54(63)>]

bigdecimal の精度の仕様は、標準添付された当初から存在しています。
どういう問題かというと、10進法での桁数で精度が保存されない事、
確度が実装されてない事、そして末尾のゼロの列を有効数字に入れられない事です。

この問題のため、たとえば「有効数字50桁のゼロ」は作れません。
残念ながら 1.9.3 に修正を間に合わせることはできそうにないので、
次のリリースまでに対応することを目指しています。


Kenta M.
Sent with Sparrow (http://www.sparrowmailapp.com)

$B;d$O@:EY$rI,?$K$9$k;v$K0UL#$,L5$$$H$O9M$($^$;$s!#(B

$B5U$KM-M}?t$N(B10$B?JE83+$rBG$A@Z$k7e?t$,>!<j$K7h$^$k;v$NJ}$K0UL#$r46$8$^$;$s!#(B

$B$U$J$P$5$s$O(B BigDecimal(Rational(Math::PI))
$B$O2?7e$GE83+$5$l$k$Y$-$@$H$*9M$($G$9$+!)(B

$B$G$-$l$P!"$=$N7e?t$r%G%U%)%k%HCM$K$7$FNI$$$H9M$($k:,5r$b4^$a$F65$($FD:$-$?$$$G$9!#(B

$B$=$l$OH=$j$^$;$s!#@:EY$r;XDj$9$k;v$K0UL#$,$J$$$H8@$C$F$$$k$N$G$J$/!“A4(B
$BBN$H$7$F@:EY$N;XDj$,E0Dl$7$F$$$J$$$N$G$”$l$P!"8=;~E@$KI,?$H$9$k0UL#$,(B
$B$h$/H=$i$J$$$H;W$$$^$9!#(B

$B<B:]$K$O!"(BRational#to_d
$B$J$I$bJQ99$K$J$C$F$$$k$o$1$G$9$+$i!"C1$K?7$7$$(B
$B5!G=$rDI2C$7$?$H$$$&$o$1$G$O$J$$$G$9$h$M!#(B

むらたです。

On Monday, August 1, 2011 at 01:45 , Kenta M. wrote:

On Monday, August 1, 2011 at 00:17 , Tadayoshi F. wrote:

だから、現時点で精度を必須にするのはあまり意味がないんじゃないですかね。
最終的にどうなるのか判らない以上、今回の仕様変更が良いのか判断できない
ですね。

1.9.3 の Rational#to_d は精度を必須とする変更を中止しています。

ごめんなさい。to_d じゃなくて BigDecimal 関数と BigDecimal.new の事を言ってる事に
先のメールを送信してから気付きました。

BigDecimal 関数と BigDecimal.new は、いままで Rational を受け付けなかったのですから、
これらが明示的な精度の指定を要求していても問題ないと考えています。

私は精度を必須にする事に意味が無いとは考えません。
逆に有理数の10進展開を打ち切る桁数が勝手に決まる事の方に意味を感じません。

ふなばさんは BigDecimal(Rational(Math::PI)) は何桁で展開されるべきだとお考えですか?
できれば、その桁数をデフォルト値にして良いと考える根拠も含めて教えて頂きたいです。


Kenta M.
Sent with Sparrow (http://www.sparrowmailapp.com)

むらたです。

On Monday, August 1, 2011 at 02:10 , Tadayoshi F. wrote:

私は精度を必須にする事に意味が無いとは考えません。
逆に有理数の10進展開を打ち切る桁数が勝手に決まる事の方に意味を感じません。

ふなばさんは BigDecimal(Rational(Math::PI)) は何桁で展開されるべきだとお考えですか?
できれば、その桁数をデフォルト値にして良いと考える根拠も含めて教えて頂きたいです。

それは判りません。精度を指定する事に意味がないと言っているのでなく、全
体として精度の指定が徹底していないのであれば、現時点に必須とする意味が
よく判らないと思います。

「精度の指定」は徹底できていると思っているのですが、まだ抜けているでしょうか。
Rational#to_d だけは、ActiveRecord のために互換性を維持するようデフォルト引き数を
維持するようにしましたが、その他の場合について変換後の桁数の指針が無い場合は
明示的に指定するように設計したつもりです。抜けがあったらご指摘ください。

現状に対する私の理解は「精度の仕様さえ整えられれば全体が上手くまとまる」です。
ですから、精度の仕様を先に修正してから変換系に手を付けろという指摘があるとしたら、
それは確かにもっともだと私も思います。
先に変換系に手を付けることになったのは、それらに対して要求があったからです。
[ruby-core:34335] の辺りのスレッドです。

実際には、Rational#to_d なども変更になっているわけですから、単に新しい
機能を追加したというわけではないですよね。

BigDecimal 関数による変換機能は、RubyKaigi で足りない機能として紹介した事があるくらいなので、
もともと導入したいと考えていたものです。実際に追加されたきっかけは上記の ML のスレッドです。
これらを追加したときには各 to_d メソッドとの対称性についてまで気を配れていませんでした。
ですから、機能が増えた当時は単に新しい機能を追加したような気分でいたと思います。
今はどうかというと、ふなばさんの指摘のおかげで気付けたので to_d まで含めて変換系として考えています。

ただし、だからといって、Rational#to_d で引き数を省略できる事をもって統一性が無いと
指摘するのは勘弁してください。
これは上述のとおり、ActiveRecord のために互換性を維持するように残しただけです。
Rational#to_d の引き数を省略すると警告が出ることからも分かってもらえると思いますが、
この機能は非推奨です。存在してはならない振る舞いだと思って頂きたいです。


Kenta M.
Sent with Sparrow (http://www.sparrowmailapp.com)

$B$?$@$7!"$@$+$i$H$$$C$F!"(BRational#to_d
$B$G0z$-?t$r>JN,$G$-$k;v$r$b$C$FE}0l@-$,L5$$$H(B
$B;XE&$9$k$N$O4J[$7$F$/$@$5$$!#(B
$B$3$l$O>e=R$N$H$
$j!"(BActiveRecord
$B$N$?$a$K8_49@-$r0];}$9$k$h$&$K;D$7$?$@$1$G$9!#(B
Rational#to_d
$B$N0z$-?t$r>JN,$9$k$H7Y9p$,=P$k$3$H$+$i$bJ,$+$C$F$b$i$($k$H;W$$$^$9$,!"(B
$B$3$N5!G=$OHs?d>)$G$9!#B8:_$7$F$O$J$i$J$$?6$kIq$$$@$H;W$C$FD:$-$?$$$G$9!#(B

$B5$$K$J$k=j$H$7$F!"(Bto_d $B<+BN$H$7$F$OL^O@!"(BNumeric $B$N(B to_x
$B$H$7$F0z?t$,I,(B
$B?$J$b$N$,DA$7$$$H$$$&;v$b$"$j$^$9!#(BObject#to_x
$B$H$7$F$bI,?$H$7$F$$$k(B
$B$N$ODA$7$$$N$+$b!#(B

$B$J$N$G!"$3$l$O$b$&JLJ*$@$H9M$($F!"$?$H$($P!"(BRational#to_d
$B$"$?$j$ODj5A(B
$B0h%(%i!<07$$$K$7$F!"(BNumeric#decimalize
$B$J$IJL$N$b$N$rMQ0U$9$k$H$+!“B>$K(B
$BJ}K!$O$J$$$N$+$H$$$&5?Ld$,$”$j$^$9!#(B

$B7W2h$O0JA0$+$i$"$C$F$b!":#2s$+$J$j92$F$F:n6H$7$?$N$O3N$+$@$H;W$$$^$9$,!"(B
$B:#$N$^$^$@$H$b$&;~4V$,$J$$$N$G!“B<ED$5$s$r?.$8$F$*G$$;$9$k$7$+$J$$!”$H(B
$B$$$&>u67$G$9$+$M!#85$+$i$"$k(B BigDecimal
$B$NLdBj$b4^$a$F!":G=E$K$I$&$J$C(B
$B$F$f$/$N$+J,$j$^$;$s$+$i!#(B