詳解! Decimal

2,513 views

Published on

とちぎRuby会議03での発表資料です。
http://regional.rubykaigi.org/tochigi03
http://www.ustream.tv/recorded/12945027/highlight/153311
http://decimal.rubyforge.org/

Published in: Technology
3 Comments
1 Like
Statistics
Notes
No Downloads
Views
Total views
2,513
On SlideShare
0
From Embeds
0
Number of Embeds
19
Actions
Shares
0
Downloads
10
Comments
3
Likes
1
Embeds 0
No embeds

No notes for slide

詳解! Decimal

  1. 1. 詳解! Decimal筑波大学情報科学類科目等履修生・Tsukuba.rb 斎藤ただし
  2. 2. 非常に軽い自己紹介 ←ぎだがんどぅ→1 なう! 2群馬  栃木  茨城
  3. 3. 感慨深い
  4. 4. 多倍長十進小数演算ライブラリ Decimal
  5. 5. Decimalとは何か?● 斎藤が書き起こしたプロダクト● 多倍長十進小数演算ライブラリ ● ふつうの小数を好きな長さだけ計算できる ● 組み込みのFloatを補う● Ruby標準添付ライブラリBigDecimalの後継を 目指す ● シンプル・高速・使いやすい・正確 decimal.rubyforge.org
  6. 6. Floatは不正確! (1/2)● 超FAQ x = 0.0 10.times { x += 0.1 } x == 1.0 #=> false!? ● 何度「バグ報告」されてるか分からない ● 例えば http://redmine.ruby-lang.org/issues/show/4394 ● “Learn floating point numbers. What Every Computer Scientist Should Know About Floating- Point Arithmetic ...” by @nalsh decimal.rubyforge.org
  7. 7. Floatは不正確! (2/2)● 10進小数が有限桁の2進小数で表現できる条件 by @mrkn ● http://d.hatena.ne.jp/mrkn/20110223 ● n 桁の10進小数は、それを10m倍して5nの倍数にで きるような自然数m≧nが存在するとき、有限桁の 2進小数で表現できる ● 0.1は、0.1 * 10 = 1 が 51 の倍数ではないので有限 桁の2進小数で表現できない● → 十進小数演算ライブラリの存在意義 decimal.rubyforge.org
  8. 8. Decimalとは何でないか?● 無限の長さの小数を計算 ● 「1 / 3」の結果は正確に保持できない ● 桁数が有限なのはFloatと一緒、あくまでも「可能 な限りの(任意の)長さ」● BigDecimalができない事ができる画期的なもの ● あくまでより良い再発明 decimal.rubyforge.org
  9. 9. っていうか何でそんなことやってるの?ちょっと俺の身の上話を 聞いてくださいよ decimal.rubyforge.org
  10. 10. πdecimal.rubyforge.org
  11. 11. 小学生● 5年生の授業参観日、算数● 円周率 π に出会う (人生初の無理数)● 先生「…という風に、ずっとに続いていきま す。」● 俺「全部調べた事もないのに、なんで分かる の?」● 先生「大きくなったら、スウガクを勉強してく ださい。」 decimal.rubyforge.org
  12. 12. 「大きくなったら、スウガクを 勉強してください。」 decimal.rubyforge.org
  13. 13. 根に持ってしまった。 decimal.rubyforge.org
  14. 14. 中学生● C言語に出会う● 当然 π を計算!● ……あれ? ● 何百桁も計算してるはずなのに出てこない ● ていうか途中から間違ってるし● C言語の小数は「固定長」だった!● 代わりに「多倍長整数」に出会う ● 手元で実装したり decimal.rubyforge.org
  15. 15. 高校生● 多倍長「整数」の計算に必要な数式を組み立て ては崩し● 「いくらでも長い整数」が扱えれば「いくらで も長い小数」も扱えるんじゃ?● AO入試で逆質問 ● 先生「んなの簡単」 ● 俺「???」● Rubyに出会う (Ruby本の出る出る詐欺未遂事件) decimal.rubyforge.org
  16. 16. 大学生● Rubyにちょっかいを出し始める● 1.8リリース、標準添付ライブラリ拡大路線● BigDecimalが飛び込んできた!!!● ソースを読んだり、数式で悩んだり● ようやく「いくらでも長い小数」を計算できる 原理を理解 decimal.rubyforge.org
  17. 17. BigDecimalのAPIにちょっかい● 2003年、1.8.0リリースの直前● 前身のBigFloatとは違う性質● なのに代わり映えしないAPI(メソッド群)● Numeric全般も気にしないオレオレAPI● →だいぶ変えてもらいました● →まだ不満● →ほぼそのまま現在に至る(1.9.2) decimal.rubyforge.org
  18. 18. 身の上をまとめると● π を計算したかった● BigDecimalには不満があった● →なら新しく作っちゃえばいいじゃない● = Decimal ! ● Decimal::Math.pi(n) #=> 小数点以下n桁のπ! decimal.rubyforge.org
  19. 19. Decimal設計上の工夫 decimal.rubyforge.org
  20. 20. 設計上の工夫● APIは最小限に● 既存クラスとの親和性を高く● 厳密さを保つ decimal.rubyforge.org
  21. 21. APIは最小限に● オレオレAPIはいらない ● クラスメソッド5個、インスタンスメソッド13個減● 「多倍長」「十進」を生かすものは残す ● d = Decimal(“1.23”) d.round(1, :up) #=> Decimal(1.3)● 必要になったら後から入れる ● 後から「消す」のは大変だよね decimal.rubyforge.org
  22. 22. 既存クラスとの親和性を高く● Rubyの数なんだからNumeric● 「小数」なんだから「だいたいFloat」● Float・他のNumericのメソッドと同じ名前では 同じ動作● Floatを返すMath.functionも Decimal::Math.functionとして実装 ● sinとかsqrtとかlogとか ● Floatと違い、何桁でも計算できます decimal.rubyforge.org
  23. 23. 厳密さを保つ● BigDecimalはFloatとの「自然な」演算が有効 ● BigDecimal(“1.23”) + 0.1 #=> 通っちゃう…不正確!● Decimalはプログラマが精度を明示しない限り 厳密さを保つ● Floatとの演算を軒並みエラーに ● 不正確さを明示 ● どうしても一緒にしたいときはDecimal#to_fして ください decimal.rubyforge.org
  24. 24. Decimal実装上の工夫 decimal.rubyforge.org
  25. 25. 実装上の工夫● コード再利用● 省メモリ decimal.rubyforge.org
  26. 26. その前に「多倍長十進小数」の 内部構造の復習 decimal.rubyforge.org
  27. 27. RubyKaigi2009… decimal.rubyforge.org
  28. 28. そもそも
  29. 29. 小数は整数の組で表せる
  30. 30. 3.14
  31. 31. (314, 2)
  32. 32. 「314」の「下から2桁目」 に小数点
  33. 33. 3.14
  34. 34. もっと長い小数でも
  35. 35. 3.14159265358979
  36. 36. (314159265358979, 14)
  37. 37. (大きい整数, 小さい整数)
  38. 38. 小数の計算 ≒整数の計算
  39. 39. 復習終わり decimal.rubyforge.org
  40. 40. 実装上の工夫● コード再利用● 省メモリ decimal.rubyforge.org
  41. 41. コード再利用 (1/2)● BigDecimalは「大きい整数」を自前で実装● それってBignumでよくない?● →やったらあっさりできた ● C API: rb_big_plus(), rb_big_mul(), …● 135,334 バイト (BigDecimal) vs 59,706 バイト (Decimal) ● 55%以上の小型化● しかも速いし (e.g. 1.9.1 → 1.9.2) decimal.rubyforge.org
  42. 42. コード再利用 (2/2)● つまり ● 実装のコンパクト化 ● 高速化● 同時に達成! ● B-) decimal.rubyforge.org
  43. 43. 省メモリ (1/2)● BigDecimal インスタンス本体 typedef struct { ← いらない VALUE obj; U_LONG MaxPrec; U_LONG Prec; S_INT exponent; short sign; short flag; U_LONG frac[1]; } Real; decimal.rubyforge.org
  44. 44. 省メモリ (2/2)● 我がDecimal インスタンス本体 typedef struct { VALUE inum; long scale; } Decimal;● スッキリ! decimal.rubyforge.org
  45. 45. という感じで● いろいろがんばりました● Ruby Summer of Codeに採択&完走、賞金$5000!● /(^o^)\ decimal.rubyforge.org
  46. 46. まとめ● Decimalはふつうの小数をふつうに計算するた めのライブラリです● 既存のBigDecimalよりおいしいです (^p^● 使ってやってください m(_ _)m decimal.rubyforge.org

×