Closed ARAN1218 closed 2 years ago
pythonはC言語やJava等と違い、int型のデータに上限がない。その為、通常ならば非常に大きな数字の階乗等の計算もオーバーフローを心配せずに実行できる。しかし、今回はオーバーフローと思わしきエラーが発生してしまっている。今回はnumpyというライブラリを用いてリスト内の要素の総積を求めるメソッドであるnp.prodを使用している。その出力が以下である。
これはnumpyがC言語で書かれたライブラリであり、C言語の制約を受けてしまうために起こる現象である。つまり、C言語と同様に約21億程度でオーバーフローを起こしてしまい、負の値を取ってしまうことがある。
これを防ぐためには、numpyを使わずに同様の処理を達成する事が求められる。現在numpyを使っている処理は
の2つである。
1つ目は簡単で、標準ライブラリであるmathライブラリのmath.factorialメソッドを用いれば良い。 問題は2つ目である。一応mathライブラリにmath.prodメソッドがあるのだが、これはPythonのバージョンが3.8以降でないと使えない。つまり、jupyter notebookのカーネルを更新する必要があると考えられ、非常に面倒である。
fisher_exact_test関数内にリスト内総積算出関数を作ってしまうのも手だが、こちらは関数のスペースを取ってしまい、美しくない。その為、最後の手段として考える。
調査の結果、functoolsライブラリとoperatorライブラリを用いることでスマートに処理できることが分かった。
pythonにてfunctoolsのreduceモジュールとoperatorのmulモジュールを用いてreduce(mul, target_list)
と記述することで、リスト内要素の総積がpythonの処理として求められる。つまり、上記のバグが起きていた計算が以下のように修正される。
これでコードの複雑性をあまり上げずにオーバーフローを起こす心配を解消できた。
cross_tabulationのfisher_exact_test.pyにて、以下の様にp値が負の値を取ってしまう場合があることを確認した。このエラーは検定を実行する上で機能不全を起こすエラーであり、どうにか対処しなくてはならない。
この例以外にも、より数値の大きいデータで実行したり、単純にマス数を増やした場合にも同様のエラーが見られたので、恐らく数値のオーバーフローだと思われる。詳細な検証は後に進めていく。