2010年03月26日

徒然なるままに0.1 + 0.2 ≠ 0.3とか

最近忙しくしてるので、生存確認代わりに、通勤中に気晴らしに書いた文章でも載せておこう。あまり意味のある文章ではないです。

0.1 + 0.2 == 0.3
この式の結果は、RubyでもPythonでもJavaでも、falseになります。

理由は、まぁ、いつものヤツです。行きつけのプログラミングカフェ(そのうち出来るかも。ホビープログラマカフェを作ろうの方とか期待)で「マスター、浮動小数点演算のいつものヤツ」と言えば通じるかもしれないアレの話です。

試しにJavaでこんな風に書いてみます。
System.out.println( 0.1 + 0.2 );

結果はこうなります。
0.30000000000000004

ちなみにJavaでこう書くとどうなるでしょう。
System.out.println( 0.1f + 0.2f == 0.3f );

結果はtrueになります。

f付けない時は倍精度の64bitだったのが、単精度の32bitになったのでズレるタイミングが変わったようです。

32bitだってズレる時はズレます。

System.out.println( 0.3f + 0.4f == 0.7f );
これの結果はfalseになります。

でも、こっちはtrueになります。
System.out.println( 0.3 + 0.4 == 0.7 );
まぁ、精度の問題で落ちるタイミングなんて、bitそれぞれってことだよね。

ところで、0.1 + 0.2の結果は、0.30000000000000004だったわけだけど、最後の数字が4って、なんか格好悪いよね。

おまえ、4ってなんだよ。精度落ちとか言いながら実は計算間違いしてるんちゃうの、と。

そこで両者を16進数で表現してみる。

System.out.println( Double.toHexString( 0.3 ) );
// 結果: 0x1.3333333333333p-2
System.out.println( Double.toHexString( 0.1 + 0.2 ) );
// 結果: 0x1.3333333333334p-2

こう書くと、あー、1ズレただけなんだなぁと思えます。人間の目ってフシアナだよね。いや、私の目だけかもしれんけど。

でも、こっちは2ズレてたりする。
System.out.println( Float.toHexString( 0.7f ) );
// 結果: 0x1.666666p-1
System.out.println( Float.toHexString( 0.3f + 0.4f ) );
// 結果: 0x1.666668p-1

ドンマイ。


実はこの辺の浮動小数の計算を私はしっかりと手計算したことがなかったりする。

仮数部と指数部があって、こんな感じで計算してるみたいなことは分かるのだけど、前から何ビットが指数だとか、指数が1001011だった場合にそれっていくつを指してるのとか、その辺は実は知らない。

これでプログラミングでご飯食べているのだから、不思議だ。まぁ、実際に概念さえわかってれば手で計算することなんてないと言えばないけどさ。一回くらいやっておくべきだよね。

時間があったらJavaのビットでやった時みたく、この辺を分かりやすい記事に起こしたいなぁと思っているのだけど、最近は忙しいのでそんな時間も取れない。


現在、1個副業っぽい話に関わっていたり、もう1個、まだ詳しい話も出来ない程度だけど新しい話が来ていたり、プライベートでは昔から尊敬していた女性と仲良くしようと頑張っていたりと、ちょっと忙しい。いや、けっこう忙しい。違う、とても忙しい。

チャンスというものは、じっくり種を蒔いて、早く花が咲かないかなぁと待って、でもいつまでも結果が出ずに「はぁ、ダメだったか」と諦めて、種を蒔いたことすらすっかり忘れた頃に、急に「おーい、咲いたぞー」という連絡が来たりする。

で、その花の咲くタイミングというのが、笑えるほど同時多発的だったりする。そんな一度に咲かれても収穫しきれないよと嘆かざるをえないような。

そういう時は無理をしてでも出来る限りの収穫をしておかないといけない。しかもけして花の形を崩したりはせずに、綺麗に収穫しないといけない。

こういう時に花を摘まずに放置したり、他の人に収穫を譲ってしまったり、いい加減な収穫をして花の形を崩してしまったりすると、その花を得るにはまた種を蒔いて長い時間待たないといけなくなる。まぁ、人にあげればいつかお返しが来ることはあるけど。

ちゃんと収穫をすると、その花からまた新しい種が取れて、すぐに新しい花が咲く。連鎖的に新しい話が発生する。チャンスはこなせばこなしただけ増えていく。

だから蒔いた種が花を咲かせた時は、当社比200%くらいの力を発揮して全部確実に綺麗にかっこ良く収穫しないといけない。摘んだ花の二乗に比例して、チャンスは広がっていくから。という話でした。

あれ、そんな話をしようとしていたんだっけ。最初の話から随分と外れてしまった気がするけど。

まぁ、いいか。さて、今日中にまとめないといけない資料が2本。頑張らねば。