2009-05-31 13 views
8

私は毎日私の会社でPython 2.4で働いています。私は標準的な数学ライブラリの多用対数関数 'log'を使用しました。log(2 ** 31、2)を入力すると31.000000000000004が返されました。Pythonでの不正確な対数

私は2の他の大国と同じことをした、そしてそれは完全に働きました。私は 'log10(2 ** 31)/ log10(2)'を実行した。31.0

より高度なバージョンで修正されたと仮定して、同じオリジナル関数をPython 3.0.1で実行しようとした。

どうしてですか? Pythonで数学的関数にいくつかの不正確さがある可能性はありますか?

+0

複製、多分誰かができる。 –

+0

私は、Python 3が浮動小数点エラーを修正していないことを指摘しておきます。代わりに、印刷出力は、スラックの代わりに、意図した浮動小数点値を表示するためにスマートなアルゴリズムを使用します。 –

答えて

44

これはコンピュータの計算で予想されます。おそらく学校で学んだ数学と一致しないような具体的な規則、例えばIEEE 754に従っています。

このが実際にの場合は、Pythonのdecimal typeを使用してください。

例:

from decimal import Decimal, Context 
ctx = Context(prec=20) 
two = Decimal(2) 
ctx.divide(ctx.power(two, Decimal(31)).ln(ctx), two.ln(ctx)) 
+22

+1はいい答えですが、主に「これが実際に問題がある場合」です。プローブは精度の低い土星に飛行しました。 – dwc

+0

確かに。イタリック体は答えの中で最も重要な部分です。 –

+0

@dwcもしオペレータがログ機能の結果をceilしていたら、それは重要だったでしょう。その後、エラーは非常に大きくなります。私の場合、私のプログラムの1つでは、私はこれをやっていました: 'a = floor(log(x、b))'そして、プログラムは 'floor(log(243,3))'出て来る4 – Rushil

17

常には0.00001%または0.00000000001のような固定値のようなパーセンテージ値のいずれか(浮動小数点演算は、それらにいくつかの誤りがあり、考慮に入れ、そのエラーを取るの等価性をチェックすると仮定します)。この不正確さは、全ての10進数が固定数のビット精度で2進数で表現できるわけではないので、与えられたものである。

あなたの特定のケースでは、Pythonが31以来、IEEE754を使用している場合でも、単精度で容易に表現する必要がありますそのうちの一つではありません。それはそれはそれは両者の直接の力のような特殊なケースを検出するためのコードを持っていないという理由だけで、のログを計算するのにかかる多くのステップの一つで精度を失うことが可能です。

+1

+1私はあなたが最後の文でそれにハンドルを持っていると思います。 –

+0

非常に興味深い。私は非常に長いコードを書いています、そして、これは私がこの現象を遭遇した最初のものです。しかし、ここでの対応の後、私は今なぜそれが起こるのかの大きな写真を見始めると思います。 –

5

浮動小数点演算は決して正確ではありません。言語/ハードウェアインフラストラクチャに対して許容可能な相対誤差を持つ結果を返します。

通常、浮動小数点演算が正確であると仮定するのは間違いです。ウィキペディア浮動小数点記事:)から"Accuracy problems" section

2

これは正常です。 log10がより正確でlog(x、y)になることを期待しています。なぜなら、対数の底辺が何であるかを正確に知っているからです。また、底10の対数を計算するためのハードウェアサポートもあります。

19

あなたは「すべてのコンピュータ科学者は、浮動小数点演算について知っておくべきこと」読みください。

http://docs.sun.com/source/806-3568/ncg_goldberg.html

+1

ありがとうございます。それは偉大な参考資料です。 –

+0

+1優れたリファレンス –

3

IEEE倍精度浮動小数点数は52 bits of precisionを持っています。 10^15 < 2^52 < 10^16のため、倍精度は15〜16の有効数字を持ちます。結果31.000000000000004は16フィギュアに匹敵しますので、期待通りの結果が得られます。

1

repr pythonの数字の匂い(float.__repr__)は、IEEE-754の計算が限界まで正確であれば、変換されたときにできるだけ実際の値に近い数字の文字列を返そうとします。あなたprintが結果を編あればいずれにせよ、あなたは気づかないでしょう。

>>> from math import log 
>>> log(2**31,2) 
31.000000000000004 
>>> print log(2**31,2) 
31.0 

printは少ない数字を表示することにより、不正確さを食料調達、(float.__str__メソッドを介して、このケースでは)文字列に引数を変換し、 :

>>> log(1000000,2) 
19.931568569324174 
>>> print log(1000000,2) 
19.9315685693 
>>> 1.0/10 
0.10000000000000001 
>>> print 1.0/10 
0.1 

usuallyuseless'答えは実際には、非常に便利です:)多年生浮動小数点質問(?なぜ私は浮動小数点エラーを取得しています)、投稿する最高の重複したQを見つけることができないの

関連する問題