浮動小数点数の話 2013年度版
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

浮動小数点数の話 2013年度版

  • 6,112 views
Uploaded on

第70回PHP勉強会の発表資料です。

第70回PHP勉強会の発表資料です。

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
6,112
On Slideshare
2,280
From Embeds
3,832
Number of Embeds
6

Actions

Shares
Downloads
8
Comments
0
Likes
13

Embeds 3,832

http://d.hatena.ne.jp 3,777
http://cloud.feedly.com 50
http://digg.com 2
http://reader.aol.com 1
https://web.tweetdeck.com 1
http://www.feedspot.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. 浮動小数点数の話 2013年度版 hnw 第70回PHP勉強会(2013/07/22) 発表資料 13年7月23日火曜日
  • 2. 自己紹介 @hnw / id:hnw 勤務先:KLab株式会社 カレーとバグが大好物 最近の興味:Zend OPcache 改造しがいがある、最近イチオシのオモチャ 13年7月23日火曜日
  • 3. 今日おはなしすること 浮動小数点数の怖い話 round関数の近況 MySQLでの小数の扱い 13年7月23日火曜日
  • 4. 浮動小数点数の怖い話 round関数の近況 MySQLでの小数の扱い 13年7月23日火曜日
  • 5. 浮動小数点数の怖い話(1) 例:ゲーム内のアイテムの売買機能 プレイヤーはアイテムを店で定価で買える 定価の10%増しで、NPCが買い取ってくれる 端数が出た場合、小数点以下切り上げ(5.5→6) 13年7月23日火曜日
  • 6. 浮動小数点数の怖い話(1) 例:ゲーム内のアイテムの売買機能 プレイヤーはアイテムを店で定価で買える 定価の10%増しで、NPCが買い取ってくれる 端数が出た場合、小数点以下切り上げ(5.5→6) 罠に気づきましたか? 13年7月23日火曜日
  • 7. 浮動小数点数の怖い話(2) 定価100コインのアイテムの売価が111コインになる! 100の10%増しなら110 のはずでは…? 実験してみる(1.1倍して切り上げ) 13年7月23日火曜日
  • 8. 何が問題だったか? 1.1倍したのが問題 1.0や0.5はピッタリ表現できるが、0.1だと誤差が入る 11.0倍して10.0で割っていれば問題なかった 13年7月23日火曜日
  • 9. 補足(1) 浮動小数点数の性質からくる問題 浮動小数点数は2進数なので、1/5は循環小数になる 有限桁(53bit)で打ち切られるので、誤差が入る PHPに限らず、多くの言語で起こる現象 10進小数クラスや有理数クラスを持つ言語もある 13年7月23日火曜日
  • 10. 補足(2) 浮動小数点数演算で誤差を避ける方法は? 浮動小数点数で「ピッタリ」表せる数を使うこと 誤差が入りうる計算を後回しにすること 整数演算だけで済む仕様に誘導するのも手 13年7月23日火曜日
  • 11. 補足(3) 浮動小数点数で無理ならgmp関数を使ってもよい BC Mathは素性が不明だわ遅いわでイマイチな印象 「その処理をPHPでやるのが正解か?」も要検討 13年7月23日火曜日
  • 12. 浮動小数点数の怖い話 round関数の近況 MySQLでの小数の扱い 13年7月23日火曜日
  • 13. こんなことがありました PHP 5.2.xのround関数の実装がイマイチというネタで炎上 http://d.hatena.ne.jp/hnw/20070515 日記書き始めて10エントリ目くらいだった まつもとゆきひろさんの日記で言及→DIS大会 13年7月23日火曜日
  • 14. 応戦してた どう見てもヤバい人です。 13年7月23日火曜日
  • 15. 当時のround関数の概要 round(x)の実装が普通と違った 普通の実装:x > 0 なら floor(x+0.5) PHPの実装:x > 0 なら floor(x+0.50000000001) 13年7月23日火曜日
  • 16. 当時のround関数の概要 round(x)の実装が普通と違った 普通の実装:x > 0 なら floor(x+0.5) PHPの実装:x > 0 なら floor(x+0.50000000001) ↑ 意味わからん 13年7月23日火曜日
  • 17. 議論の概要 PHP以外の人「これだからPHPは」 僕「指摘が浮動小数点数的に間違ってるけど?」  「RubyやPythonやPerlのコレもバグじゃね?」 浮動小数点数まわりのバグが結構見つかった PHPがひどい点については基本スルー 13年7月23日火曜日
  • 18. 今どうなってるか(1) PHP 5.3以降、round関数の仕様と実装が変わりました 詳細:https://wiki.php.net/rfc/rounding x > 0 なら floor(x+0.5) と、他の言語と同様の実装 大きい数にだけ起こる、直しにくいバグが残っている http://d.hatena.ne.jp/hnw/20110407 13年7月23日火曜日
  • 19. 今どうなってるか(2) 僕が当時指摘したバグはRuby 1.8.7とPython 2.7.3で すべて修正されている すげえ! なおPerl 5.14.4では修正されていない模様 13年7月23日火曜日
  • 20. 浮動小数点数の怖い話 round関数の近況 MySQLでの小数の扱い 13年7月23日火曜日
  • 21. MySQLでの小数 小数リテラルは固定小数点数になる 固定小数点数=桁数と小数点の位置が決まっている表現 MySQLではDECIMAL型が対応する DECIMAL(10, 2) : 全10桁、小数以下2桁 13年7月23日火曜日
  • 22. 固定小数点数の世界 誤差の問題から解放される これで平和が訪れた! = true 13年7月23日火曜日
  • 23. 固定小数点数の世界 誤差の問題から解放される これで平和が訪れた! と思ったでしょ?残念! = true 13年7月23日火曜日
  • 24. 浮動小数点数の恐怖再び 文字列リテラルに対して加減算→自動キャスト 文字列を数値にキャスト→浮動小数点数になる = false 13年7月23日火曜日
  • 25. イマイチなPDOの仕様 PDOはプレースホルダの展開時に PHP変数の型が文字列なら必ずクォーティングする PDO::PARAM_INTの指定はbool型のみ影響する 参照:http://stackoverflow.com/questions/833510/ php-pdobindparam-data-types-how-does-it-work 数値なのに文字列型になっている場合は要注意 13年7月23日火曜日
  • 26. 小数を避ければ平気か 「DB上で小数なんて使わないから自分には関係ない」 とか思ってませんか 小数点が無くても浮動小数点数を経由します = true 13年7月23日火曜日
  • 27. 何が起きたのか? 文字列をキャストして浮動小数点数になった 2^53以上の整数は浮動小数点数で正しく表現できない 前のページの例では、1を足したはずが2増えた 10進で16桁以上の整数を扱う場合は要注意 BIGINT型など 13年7月23日火曜日
  • 28. まとめ 浮動小数点数は罠がたくさん 罠を避けるには知識が必要 PHPのround関数は昔よりマトモになった MySQLにも浮動小数点数の罠がある PHPだとPDOがイマイチなせいで罠を踏みやすい 13年7月23日火曜日
  • 29. ご静聴 ありがとう ございました 13年7月23日火曜日