百日半狂乱

Shut the fuck up and write some code!!

0.1 + 0.1 + 0.1 == 0.3 ?

パーフェクトPythonを写経中に0.1 + 0.1 + 0.1について書いてあったのでメモ.

Pythonのfloat(浮動小数点数型)は、大抵の場合はCのdouble型を使って実装されており、近代的なコンピュータの場合53ビットの精度らしい.

Python

$ python
Python 2.7.3 (default, Feb 27 2014, 19:58:35) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1 + 0.1 + 0.1 == 0.3
False
>>> 0.1 + 0.1 + 0.1
0.30000000000000004

例が2系だけど3系でもFalseになる*1

Python0.1 + 0.1 + 0.10.3として扱いたい場合はdecimalモジュールをimportしてこれを用いれば良い.

Ruby

$ irb
irb(main):001:0> 0.1 + 0.1 + 0.1 == 0.3
=> false

Rubyもfalse.

パーフェクトPythonでは、もう1つJavaを例として、0.1 + 0.1 + 0.1 == 0.3がfalseになる様子が挙げられていたので、Cでも見てみた.

C

0.1 + 0.1 + 0.1 == 0.3 ?

$ gcc -Wall test_double_dig.c
$ ./a.out                   
False:0.3000000000000000444089209850062616169452667236328125000000000000000000000000000000000000000000000000

詳しいことはWikipedia参照:コンピュータの数値表現

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

*1:ちなみに、パーフェクトPythonはPython3.3対応の書籍です.念の為.

awkで0~1の乱数を生成する

シェルスクリプトを書いていて、ふと0~1の乱数をお手軽に生成したくなったので、実験結果をメモ.

awkには組み込みでrand()という関数が用意されていて、例えば以下のような形で呼び出すたびに0~1の範囲の乱数を生成してくれる.

awk 'BEGIN{ srand('"$RANDOM"'); print rand() }'

ここでは環境変数RANDOMを組み込み関数srand()のseedとしている.組み込み関数についてはman awkを叩く.

続きを読む

世にも恐ろしいSIGPIPE、ソケットプログラミングの落とし穴

前回、「次回もシグナルのことを書く」と書いたのでシグナルのことを書く*1.

ソケットプログラミングの落とし穴は色々あるけど、ここでは個人的に嵌ったシグナル関連の落とし穴に関して書き殴る.

結論から書くと、コネクションが切れたソケットに書き込み(send(2)とかwrite(2)とか、同じものだけど)を行うと、SIGPIPEシグナルが発生してプロセスが強制終了するので、きちんとSIGPIPEシグナルをハンドリングしておこうという話.

以下では、サンプルコードを使って、実際にパイプの書き込み先をkillして、SIGPIPEの発生を疑似体験してみる.

*1:前回から115日が経っている.挫折したアドベントカレンダーもそうだけど、やはり連載宣言はするものじゃない.自分のような興味関心がブレまくる人間が連載宣言をしても、宣言した時をピークにモチベーションは下がり続ける.インプットのためのアウトプット、所詮メモの大原則を忘れている.

続きを読む

POSIX.1「signal(2)は古い、sigaction(2)を使え。」

過去に何回かシグナルに関する話をしたが、今回と次回もシグナルの話にしようと思う.

シグナルそのものについてはsignal(7)のmanページを参照する.

ここでは、シグナルを捕捉する側の話をする.

主に移植性の問題で、signal(2)ではなくsigaction(2)を使うべきだが、sigaction(2)はそのままだと使いにくいので、ラッピングして使い易くして、ちょっとだけ遊んでみた.

続きを読む