6

Python の float (および精度) の基になるデータ構造に関する質問があります。

>>> b = 1.4 + 2.3
>>> b
3.6999999999999997

>>> c = 3.7
>>> c
3.7000000000000002

>>> print b, c
3.7  3.7

>>> b == c
False

b と c の値はマシンに依存しているようです。これらはターゲット値に最も近い数値ですが、まったく同じ数値ではありません。私は、'Print' で '正しい' 数値が得られるように監督されていました。ある人は、Python が私たちに真実を伝えることを選んだのに対し、print は '嘘をついている' ためだと言いました。

私の質問は次のとおり

です。 1.嘘をつく方法は?たとえば、関数では 2 つの値を取り、それらが同じ場合に戻ります。上記のbとcのように?それを行うための明確に定義されたアルゴリズムはありますか?浮動小数点計算が含まれている場合、すべての言語 (C/C++) でこの種の問題が発生すると言われましたが、どのようにこれを「解決」しますか?

2. 最も近い数値を格納する代わりに、実際の数値を格納できないのはなぜですか? それは制限ですか、それとも効率のための取引ですか?

どうもありがとうジョン

4

6 に答える 6

7

最初の質問への回答については、Python のソースからの次の (少し圧縮された) コードをご覧ください。

#define PREC_REPR       17
#define PREC_STR        12

void PyFloat_AsString(char *buf, PyFloatObject *v) {
    format_float(buf, 100, v, PREC_STR);
}

void PyFloat_AsReprString(char *buf, PyFloatObject *v) {
    format_float(buf, 100, v, PREC_REPR);
}

したがって、基本的にrepr(float)は、17 桁の精度でフォーマットされた文字str(float)列を返し、12 桁の精度の文字列を返します。ご想像のとおり、変数名をprint使用str()してインタープリターに入力すると、 が使用されますrepr()。わずか 12 桁の精度で「正しい」答えが得られたように見えますが、それは単に、期待値と実際の値が 12 桁まで同じであるためです。

違いの簡単な例を次に示します。

>>> str(.1234567890123)
'0.123456789012'
>>> repr(.1234567890123)
'0.12345678901230001'

2 番目の質問については、Python チュートリアルの次のセクションを読むことをお勧めします: Floating Point Arithmetic: Issues and Limitations

基数 10 の 10 進数を基数 2 で格納する場合、他のどの表現よりも効率的で、メモリが少なく、浮動小数点演算が高速ですが、不正確さに対処する必要があります。

JBernardo がコメントで指摘したように、この動作は Python 2.7 以降では異なります。上記のチュートリアル リンクからの次の引用は、違いを説明しています (0.1例として使用)。

Python 2.7 および Python 3.1 より前のバージョンでは、Python はこの値を有効数字 17 桁に丸め、'0.10000000000000001' を与えていました。現在のバージョンでは、Python は、真の 2 進数値に正しく丸められる最小の小数に基づいて値を表示し、単純に「0.1」になります。

于 2011-07-18T23:20:18.637 に答える
2

悪名高い論文を読む必要があります。

すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと

「CACHED」と書かれたリンクをクリックして、論文を PDF 形式でダウンロードします。

于 2011-07-18T23:31:42.063 に答える
1

1.4と2.3の数値も正確に表されていないため、計算結果は異なります。それらを追加すると、精度の制限も蓄積されます。

すべての浮動小数点数の精度には制限があり、浮動小数点数は通常内部で(基数10ではなく基数2を使用して)表現されるため、人間が正確に表現しやすいと認識している数値には制限が適用されます。

ほとんどのアプリケーションでは精度が十分であるため、精度の制限が計算で問題になることはめったにありません。一方、浮動小数点数を比較する場合は、制限された精度を考慮する必要があります。

これは通常、数値を減算し、数値と比較して差が十分に小さいかどうかを確認することによって行われます。

したがって、たとえば、次の場合:

abs(b - c) < abs(b) / 1000000000000

そうすれば、それらは等しいと見なすことができます。考慮したい桁数は、浮動小数点数の精度、つまり、単精度または倍精度の数値を使用しているかどうか、および数値に到達するために実行した計算によって異なります。精度の限界は計算ごとに累積されるため、等しいと見なされる場合のしきい値を下げる必要がある場合があります。

浮動小数点数を表示する場合、精度に応じて丸められます。たとえば、15桁を正確に表すことができる場合は、表示する前に13桁に丸めることができます。

浮動小数点数は、高速計算を目的としています。数値を正確に格納できるDecimalなどの他のデータ型があります。これらは、たとえば通貨値を格納するために使用されます。

于 2011-07-18T23:29:04.213 に答える
0

浮動小数点数は不正確です。それは表現方法の一面です。これがなぜであるかについての正確な裏付け情報がたくさんあります。浮動小数点数を提供するほとんどすべてのプラットフォームで問題になると言えば十分です。

不正確さに対処する最良の方法は、信頼区間を設けることです。つまり、2つの計算されたフロートの等価性の比較は、表現がわずかにずれている可能性があるため問題になる可能性があります。したがって、これに対処する方法は、2つを減算し、差が小さいことを確認することです。量。多くのライブラリにはすでにこの種の機能がfloatに組み込まれていますが、疑わしい場合は自分で実装するのは特に難しくありません。

于 2011-07-18T23:05:14.913 に答える
0

すべての数値は限られた数のビットに格納されるため、実際の数値を格納することはできず、最も近い数値を格納する必要があります(分数1/3を想像してみてください。10 進数を使用して紙に格納する場合は、世界の樹木資源)。代替手段は、たとえば Mathematica で見つけることができるシンボリック表現です。これは単に and として保存さ1/3れますが、マシンから遠く離れており、計算が遅くなり、複雑になります。13

人々がここに投稿しているいくつかのリンクを見て、浮動小数点数について読んでください...少し怖いですが、もうマシンを信頼することはできません.

于 2011-07-18T23:31:37.710 に答える
0

この講義は、変数がどのようにメモリ内に保存されるかについての非常に良い洞察であり、教授は、あなたが見ている予期しない結果をもたらす例を含めています.
http://www.youtube.com/watch?v=jTSvthW34GU 数値を比較する必要がある場合は、最初に両方を整数としてキャストします。テストを実行すると、それらが等しいことがわかります。

于 2011-07-18T23:21:27.453 に答える