4

注意: この質問は有効数字に関するものです。「小数点以下の桁数」などの問題ではありません。

編集: この質問は、10 進数モジュールの有効数字の複製ではありません。2 つの質問は、まったく異なる問題について尋ねています。関数 about が特定の入力に対して目的の値を返さない理由を知りたいです。decimal モジュールの有効数字に対する回答は、この質問に対応していません。


次の関数は、指定された有効数字数の float の文字列表現を返すことになっています。

import decimal

def to_sigfigs(value, sigfigs):
    return str(decimal.Context(prec=sigfigs).create_decimal(value))

一見すると、うまくいくように見えます:

print to_sigfigs(0.000003141592653589793, 5)
# 0.0000031416

print to_sigfigs(0.000001, 5)
# 0.0000010000

print to_sigfigs(3.141592653589793, 5)
# 3.1416

...しかし

print to_sigfigs(1.0, 5)
# 1

最後の式 (IOW、1.0 の有効数字 5 桁の表現) の目的の出力は、文字列 '1.0000' です。実際の出力は文字列 '1' です。

私は何かを誤解していますか、それともバグdecimalですか?

4

2 に答える 2

5

コンテキストの精度は最大精度です。操作がコンテキストの精度よりも少ない桁数の Decimal を生成する場合、コンテキストの精度までパディングされません。

を呼び出すとto_sigfigs(0.000001, 5)0.000001ソース コードから 2 進浮動小数点への変換により、 には既にいくつかの丸め誤差があります。実際には 9.99999999999999954748111825886258685613938723690807819366455078125E-7 です。それを有効数字5桁に丸めると、 になりますdecimal.Decimal("0.0000010000")

一方、1 は 2 進浮動小数点で正確に表現できるため、1.0正確に 1 です。これを 10 進数で表現するには 1 桁しか必要ないため、コンテキストの精度は丸めを必要とせず、1 桁の Decimal 結果が得られます。 .

于 2015-12-10T21:24:39.920 に答える
2

バグですか?わかりません。ドキュメントがその決定を下すのに十分なほどきついとは思いません。確かに意外な結果です。

もう少しロジックを追加して、独自の関数を修正することができます。

def to_sigfigs(value, sigfigs):
    sign, digits, exponent = decimal.Context(prec=sigfigs).create_decimal(value).as_tuple()
    if len(digits) < sigfigs:
        missing = sigfigs - len(digits)
        digits = digits + (0,) * missing
        exponent -= missing
    return str(decimal.Decimal((sign, digits, exponent)))
于 2015-12-10T22:15:44.783 に答える