Python 3: Deep Dive (Part 1 - Functional): 等価性テスト (セクション4-4/11)
浮動小数点数は2進数で正確に表現できず、等価性テストにはイプシロン値を用いる必要がある。
浮動小数点数を整数に変換する際には、切り捨て、フロアリング、シーリングの方法があり、それぞれデータ損失が発生する。
Pythonの`round()`関数はバンカーの丸めを使用し、ゼロから遠ざかる方向への丸めはカスタム実装が必要。
はじめに
Python 3: Deep Dive (Part 1 - Functional)コースを進める中で、セクション4では数値型、特に浮動小数点数(floats)の複雑さに触れます。レッスン38から43では、浮動小数点数の等価性テスト、整数への強制変換、および丸めについて探求し、それぞれが独自の課題と細かな点を提示します。本記事では、これらの重要な概念をまとめ、講義やコーディングセッション、そして実践的なJupyterノートブックから得た洞察を結びつけています。
浮動小数点数と等価性テスト
浮動小数点の精度の問題
コースは、浮動小数点数の計算における「奇妙さ」でよく知られている問題から始まります。例えば、以下のコードを考えてみましょう:
a = 0.1 + 0.1 + 0.1
b = 0.3
print(a == b) # 出力: False
一見すると、`a` と `b` は等しいと期待されます。しかし、浮動小数点数が2進数でどのように保存されるかにより、この比較は `False` を返します。この差異は、浮動小数点数が2進数で正確に表現できないために発生し、内部的にわずかに異なる表現が生じるためです。
イプシロンを使用した比較
このような固有の制限を踏まえ、浮動小数点数をどのように信頼性をもって比較すれば良いでしょうか?その解決策は、"イプシロン" 値と呼ばれる小さな許容範囲を使用して、2つの浮動小数点数が等しいと見なすことにあります。このアプローチは、2つの数値の絶対差がイプシロンより小さいかどうかをチェックします:
epsilon = 1e-9
is_equal = abs(a - b) < epsilon
Pythonの`math.isclose()`関数はこのロジックをカプセル化し、様々なケースを処理するために相対誤差と絶対誤差の両方を組み合わせます。例えば、大きな数値とゼロに近い数値を比較する場合、異なる戦略が必要です。`isclose()`関数は、コースのコーディング演習で示されているように、柔軟で正確な浮動小数点数の比較を可能にします。
浮動小数点数を整数に強制変換する
データの損失を理解する
次に、浮動小数点数を整数に変換するプロセスに進みますが、これは本質的にデータ損失を伴います。この変換は、切り捨て、フロアリング、シーリングといったいくつかの方法で実行できます。
切り捨て:この方法では、浮動小数点数の小数部分が単に無視され、整数部分のみが返されます。例えば、`math.trunc(10.6)`は`10`を返します。
フロアリング:`math.floor()`関数は、浮動小数点数以下の最大の整数を返しますが、これは負の数の場合、切り捨てとは異なる結果を返すことがあります。例えば、`math.floor(-10.6)`は`-11`を返しますが、切り捨てでは`-10`を返します。
シーリング:逆に、`math.ceil()`は浮動小数点数以上の最小の整数を返します。例えば、`math.ceil(10.2)`は`11`を返します。
これらの方法は、丸めの決定が計算に大きく影響する数値データを扱う際に重要です。
浮動小数点数の丸め
Pythonにおける丸めのメカニズム
最後に、コースでは丸めについて説明しますが、これは一見簡単そうでありながら実際には複雑なテーマです。Pythonの組み込み関数`round()`は、指定された桁数に浮動小数点数を丸めますが、そのタイブレイク方法が驚くかもしれません。
バンカーの丸め(最近接偶数への丸め):Pythonは「バンカーの丸め」または「最近接偶数への丸め」として知られる戦略を使用します。この方法では、最も近い数値に丸められますが、引き分けの場合は最も近い偶数に丸められます。例えば:
round(1.25, 1) # 出力: 1.2
round(1.35, 1) # 出力: 1.4
この方法は、常に丸め上げまたは丸め下げを行う場合に比べて、計算全体において偏りが少なくなります。
ゼロから遠ざかる方向へのカスタム丸め:もし、より伝統的な丸め方法(ゼロから遠ざかる方向への丸め)を好む場合、Pythonにはこれを実現する組み込み関数がありません。しかし、次のようにして自分で実装することができます:
def custom_round(x):
from math import copysign
return int(x + 0.5 * copysign(1, x))
この関数は、引き分けの場合には常にゼロから遠ざかる方向に丸めることで、学校で教えられる一般的な丸めルールに合わせます。
結論
浮動小数点数の計算、整数への強制変換、および丸め方法の詳細を理解することは、Pythonで数値データを扱う誰にとっても重要です。Python 3: Deep Dive (Part 1 - Functional)コースは、これらの課題に対処するための知識とツールを学習者に提供します。複雑な計算、金融データ、または科学的な計算に取り組む場合でも、これらの概念を習得することで、コードの精度と信頼性を向上させることができます。
これらのトピックに関するハンズオンの例や詳細な洞察を得るために、提供されたJupyterノートブックをぜひご活用ください。楽しいコーディングをお楽しみください!
この記事が気に入ったらサポートをしてみませんか?