import sys
"""
浮動小数点数の累積加算と等値判定の注意点を示すスクリプト。
このスクリプトは、コマンドライン引数から`h`と`n`の値を受け取り、`h`を`n`回加算した結果が`answer`と
等しくなるか、また許容誤差範囲内にあるかを検証します。
浮動小数点数の精度問題による厳密な等値判定の困難さを示すことを目的としています。
例えば、0.01を100回加算した場合に1.0と厳密に一致しない可能性を示します。
:doc:`bad_if_usage`
"""
#===================
# parameters
#===================
h = 0.01
n = 100
answer = 1.0
eps = 1.0e-10
[ドキュメント]
def getintarg(iarg, defval = None):
"""
コマンドライン引数から整数値を取得します。
sys.argvから指定されたインデックスの引数を整数に変換して返します。
変換に失敗した場合や引数が存在しない場合は、デフォルト値を返します。
:param iarg: int: 取得する引数のsys.argvにおけるインデックス。
:param defval: Optional[int]: 変換失敗時または引数がない場合に返すデフォルト値。デフォルトはNone。
:returns: Optional[int]: 変換された整数値、またはデフォルト値。
"""
try:
return int(argv[iarg])
except:
return defval
[ドキュメント]
def getfloatarg(iarg, defval = None):
"""
コマンドライン引数から浮動小数点数を取得します。
sys.argvから指定されたインデックスの引数を浮動小数点数に変換して返します。
変換に失敗した場合や引数が存在しない場合は、デフォルト値を返します。
:param iarg: int: 取得する引数のsys.argvにおけるインデックス。
:param defval: Optional[float]: 変換失敗時または引数がない場合に返すデフォルト値。デフォルトはNone。
:returns: Optional[float]: 変換された浮動小数点数、またはデフォルト値。
"""
try:
return float(argv[iarg])
except:
return defval
argv = sys.argv
narg = len(argv)
if narg <= 2:
print("")
print("Usage: python bad_if.py h n answer")
print(" Check the condition h * n == answer")
print("")
exit()
else:
h = getfloatarg(1, h)
n = getintarg(2, n)
answer = getfloatarg(3, answer)
#===================
# main routine
#===================
v = 0.0
for i in range(n):
v += h
print("")
print(f"Summing up {h} for {n} times: v = {v}")
print(f"v == {answer}?: {v == answer}")
print(f"|v - {answer}| < {eps}?: {abs(v - answer) < eps}")
print("")