2011-01-12 16 views
12

浮動小数点の制限が計算にエラーを引き起こす原因を特定する方法を教えてください。たとえば、次のコードです。浮動小数点の問題を理解する

CalculateTotalTax = function (TaxRate, TaxFreePrice) { 
    return ((parseFloat(TaxFreePrice)/100) * parseFloat(TaxRate)).toFixed(4); 
}; 

私は、この方法で間違った結果をもたらした2つの値を入力できませんでした。 toFixed(4)を削除した場合、計算がどこで精度を失うのかがわかります(小数点第6位付近)。しかし、私が浮動小数点を理解していることは、たとえ小数であっても表現できないことや誤解を招くことがあり、小数点以下4桁を常に正確に表すことができるということです。

MSDN)これは、それらが フォームK/ (2^n個のバイナリ分数(ない任意の量の正確な 表現を保持することができないことを意味... suchとして

をフロートを説明kおよびnは整数)

これは、すべての浮動小数点数(javascriptで使用されているものを含む)に適用されます。

基本的に私の質問はこれまでに残っています。どのような特定のメソッドが浮動小数点演算のエラーに脆弱であるか、それらのエラーがどの精度で実現するのか、それらのエラーを生成するために必要な入力があるかどうかを判断する方法はありますか?

うまくいけば、私が求めていることは理にかなっています。すべてのコンピュータ科学者はポイント浮動について知っておくべきことを読み取ることで

+0

これはおそらくこのトピックに関連しています:http://en.wikipedia.org/wiki/Machine_epsilon –

+0

*トニー・ポニー*、[Jon Skeet](http://stackoverflow.com/users/22656)/jon-skeet)は、優れた説明をしています(http://codeblog.jonskeet.uk/2009/11/02/omg-ponies-aka-humanity-epic-fail/)。読みやすく、わかりやすく面白く面白くなく面白く、このテーマによく投稿される[いくつかのリンク](http://docs.sun.com/source/806-3568/ncg_goldberg.html)ほど重くはありません。 – MarkJ

答えて

10

スタート: http://docs.sun.com/source/806-3568/ncg_goldberg.html

短い答え:(JavaScriptでデフォルトです)倍精度浮動小数点数は、精度の約16桁を持っています。丸めはプラットフォームによって異なる場合があります。一貫して正解を得ることが絶対に不可欠な場合は、合理的な算術演算を自分で行う必要があります(これは難しくありません - 通貨の場合は100を掛けて整数として格納してください)。

しかし、高い精度で回答を得るには十分ですが、浮動小数点数は、特に倍精度で十分です。

4

あなたは今、山車を扱う必要がある二つの重要なことがあります。

1 - あなたはmachine epsilonに注意する必要があります。あなたはどれくらいの精度を知る。

2 - You は、if two values are equal in base 10, they are equal in base 2 in a machine with precision limitとするべきではありません。

if ((6.0/10.0)/3.0 != .2) { 
     cout << "gotcha" << endl; 
} 

ナンバー2には、あなたが平等のための浮動小数点数を比較しないように十分説得力があり代わりに、しきい値と大なりまたはオペレータに満たないが、比較のために使用することができる

+1

番号2は、「浮動小数点数を平等に比較しないでください」という意味ではありません。結局のところ、10進数を平等のために比較しないでください。つまり、理解できないコードを書くべきではありません。浮動小数点の仕組みを学ぶために時間をかけてください。 –

+0

あなたが言ったように、浮動小数点を学ぶのに時間がかかるはずです。 (0.1 == 1/10)のようなものは無邪気に見えます。だから誰もそれが以前に読んでいない限り、バグを引き起こすとは思わないでしょう。数学の基礎について話していても、10 = 9.999 ...または10進数を2進数に変換する方法は多くの人が知っているわけではありません。 –

+1

なぜなら '.1!= 1/10'は' 1/10 == 0'であるからです。あなたは整数除算を使用しています。 –

1

いや、数小数点以下の桁数は、表現できるものとは関係ありません。

.1 * 3、または162.295/10、または24.0 + 47.98を試してください。それらはJSの私のために失敗する。しかし、24.0 * 47.98は失敗しません。

あなたの3つの質問に答えるには、任意の精度の操作は潜在的に脆弱です。特定の入力が質問されるかどうかは、私は答えがわかりませんが、私は勘違いしています。いくつかの要因があります。 1)実際の答えが最も近い二分法にどのくらい近いか。 2)計算を実行するエンジンの精度。 3)計算を実行するために使用される方法(例えば、ビットシフトによる乗算は、繰り返し加算による乗算とは異なる結果をもたらすことがある)

2

その他の回答は、この問題を理解するのに良いリソースを指摘している。あなたのコードで実際に金銭的価値を使用している場合(あなたの例のように)、Decimal型(.NetのSystem.Decimal)を好むべきです。これらは、浮動小数点の使用によるドメインの丸めの問題の一部を回避し、ドメインの適合性を高めます。

関連する問題