0

いまだに正確な結果が得られません。最大は何ですか。できるだけ正確にしたい場合、表示する必要がある小数の量は?

いくつかのコード (コピーして貼り付けてテストする準備ができています):

// Test with 5 decimals 
$a = 0.00001;
echo bcadd($a,$a,5) . '<br/>';
echo bcadd($a,$a,6) . '<br/>';
echo number_format(bcadd($a,$a,5),5) . '<br/>';
echo number_format(bcadd($a,$a,5),6) . '<br/>';
echo bcadd(0.00001,0.00001,20) . '<br/>';
echo number_format(bcadd($a,$a,20),5) . '<br/>';
echo number_format(bcadd($a,$a,20),21) . '<br/><br/>';

/* Output:
0.00000
0.000000
0.00000
0.000000
0.00000000000000000000
0.00000
0.000000000000000000000
*/

// Test with 4 decimals
$a = 0.0001;
echo bcadd($a,$a,5) . '<br/>';
echo bcadd($a,$a,6) . '<br/>';
echo number_format(bcadd($a,$a,5),5) . '<br/>';
echo number_format(bcadd($a,$a,5),6) . '<br/>';
echo bcadd(0.00001,0.00001,20) . '<br/>'; // wtf? this outputs 0 too?
echo number_format(bcadd($a,$a,20),5) . '<br/>';
echo number_format(bcadd($a,$a,20),21) . '<br/>';

/* Output:
0.00020
0.000200
0.00020
0.000200
0.00000000000000000000
0.00020
0.000200000000000000010
*/

答えは 4 だと推測する必要がありますか ??? しかし、コメントのある行にはまだ問題があります

編集:誰も私のテストを理解していないと思います。フロートが不正確であることは知っています。しかし、一方は 1 != 0.98990123 であり、もう一方は 1 != 0.0000 です。bc* 関数の精度として 4 を設定すると、0.0000 ではなく、少なくとも 0.9899 (完全な答えが 1 の場合) になると予想されます。1つは「無限の精度に対して完全に正確ではない」ことであり、もう1つは「まったく役に立たない」ことです。

編集2:@Michael Borgwardtには解決策があります

4

4 に答える 4

4

最大は何ですか。できるだけ正確にしたい場合、表示する必要がある小数の量は?

問題は、浮動小数点計算から正確な値を取得しようとすることから始まります。一般に、表現エラーのため、浮動小数点計算から正確な値を取得することはできません。値 0.0001 は 2 進浮動小数点で正確に表すことができないため、実際に格納された値は 0.0001 とはわずかに異なり、すでに不正確になっています。最下位桁が不正確になることを予期する必要があります。より多くの小数を表示しても、計算がより正確になるわけではありません。固有の不正確さがより目に見えるようになるだけです。

正確さが必要な場合は、別のデータ型を使用するか (bcadd は文字列を受け入れますが、float から文字列への変換は依然として不正確になる可能性があります)、正確な回答とはわずかに異なる回答を許可するようにプログラムを変更する必要があります。

有用な回答を表示したいだけの場合は、アプリケーションにとって意味のある精度で表示できます。七面鳥を調理するためにオーブンを設定する温度を計算している場合は、答えをいくつかの有効数字に丸めることで問題ありません。科学計算を行っている場合、有効数字を 3 桁、4 桁、またはそれ以上表示したい場合があります。100% の精度が必要な場合は、設計を再考する必要があります。

于 2010-11-27T15:41:46.750 に答える
3

"bcadd" には 3 つの引数が必要です。最初の 2 つは、左右のオペランドを表す文字列と、結果の小数点以下の桁数を表す 1 つの整数です。この関数は文字列を出力します。5 番目の結果エコーで、整数の代わりに文字列値を使用してみてください。

また、浮動小数点数の精度について (PHP.net より):

float のサイズはプラットフォームに依存しますが、一般的な値は約 14 桁の精度で最大 ~1.8e308 です (64 ビット IEEE 形式)。

于 2010-11-27T15:42:45.843 に答える
2

問題の主な原因は、フロート リテラルを使用していることです。これにより、コードがコンパイルまたは解釈されて2 進数の小数に変換されるときに、丸め誤差が発生します。

その時点で、あなたはすでに負けています - bc 数学関数を使用しても役に立ちません。これらを正しく使用するには、文字列リテラルを使用する必要があります。

echo bcadd('0.00001','0.00001',20);

印刷します:

0.00002000000000000000
于 2010-11-27T15:44:32.223 に答える
-1

BCMath ライブラリを使用してみてください。基本的には数値を文字列として保存しますが、数値に算術演算を実行できます。

非常に大きな数または非常に小さな数の処理

于 2010-11-27T15:43:32.850 に答える