質問

別の数学計算の問題をもう一度取得します。

$a = 34.56

$b = 34.55

$ a 計算を行ってこの数字を取得します

$ b は、この数値を得るために0.05に最も近い丸めを行っています

何が起こるか

$c = $b - $a

おそらく-0.01であるべきですが、 $ c が表示されることをエコーアウトします-0.00988888888888

n umber_format($ c、2)を使用しようとしましたが、出力は0.00です

$ a $ b が正確に2桁の小数で、後ろに隠し番号がないことを確認するにはどうすればよいですか。

私のPHP知識ではnumber_formatは表示をフォーマットすることしかできませんが、値は実際には小数2ではありません

ここから助けが得られるといいのですが。これは本当にイライラしました。

役に立ちましたか?

解決

sprintf (&quotをお試しください;%。2f&quot ;, $ c);

浮動小数点数は2の累乗に基づいてIEEE表記で表されるため、終端の10進数は終端の2進数ではない場合があります。そのため、末尾の数字が表示されます。

Variable Length Coderで示唆されているように、必要な精度がわかっていて変更されない場合(お金を扱う場合など)は、固定小数点数を使用することをお勧めします。ドルより

$a = 3456;

$b = 3455;

$c = $b - $a;

sprintf ("%.2f", $c/100.0);

この方法では、印刷する前に多くの計算を行う場合、丸め誤差はありません。

他のヒント

round() を使用:

$c = round($b - $a, 2);

注:必要に応じて丸めモードを選択することもできます。

編集: OK sprintf() number_format()が何をしていないかわかりません:

$c = number_format($b - $a, 2);

vs

$c = sprintf("%.2f", $b - $a);

ネイティブ計算:

$a = 34.56;
$b = 34.55;
$c = $b - $a; // -0.010000000000005    

期待どおりに動作します(実数の計算には常にBC関数を使用し、問題はすべてのCベースのプラットフォームにあります):

$a = '34.56';
$b = '34.55';
$c = bcsub($b, $a, 4); // -0.0100    

最近、floatで計算を行うときにこの問題に遭遇しました。たとえば、2つの浮動小数点があり、それらを減算してフォーマットすると、値は-0.00でした。

$floatOne = 267.58;
$floatTwo = 267.58;
$result = number_format($floatOne - floatTwo, 2);
print $result; //printed a string -0.00

私がしたことは:

$result = abs($floatOne - $floatTwo);// Made the number positive
print money_format('%i', $result); // printed the desired precision 0.00

私のソリューションでは、floatOneがfloatTwoより小さくなることはありません。 money_format 関数は、システムにstrfmon機能がある場合にのみ定義されます。 Windowsはサポートしていません。

浮動小数点数のトラップの1つに遭遇しました。それらは常に正確な小数を表すことはできません。正確な10進数値が必要な場合は、整数を使用し、最後に必要な精度で除算することをお勧めします。

たとえば、ドル(またはお好みの通貨)を表すフロートで計算を行う場合、実際には整数セントで計算することができます。

bcmathライブラリを使用するだけで、これらすべての問題を非常にきれいに回避できます。

ドキュメントを読んで、引数を文字列として渡すか数値データ型として渡すかを注意してください。

まだ誰かが浮動小数点の減算がエラーまたは奇妙な値を引き起こす同様の問題でこのページに到達した場合。 この問題についてもう少し詳しく説明したいと思います。原因は浮動小数点数です。 また、オペレーティングシステムやプログラミング言語のバージョンが異なると、動作が異なる場合があります。

問題を説明するために、以下に簡単な例を挙げて理由を説明します。

PHPに直接関連するものではなく、バグでもありません。 ただし、すべてのプログラマはこの問題に注意する必要があります。

この問題は20年前にも多くの命を奪いました。

1991年2月25日に、MIM-104パトリオットミサイルバッテリーの浮動小数点計算のこの問題により、サウジアラビアのダーランに到着するスカッドミサイルを迎撃できなくなり、米陸軍第14クォーターマスター分離隊からの28人の兵士が死亡しました。

しかし、なぜそれが起こるのですか?

理由は、浮動小数点値の精度が限られているためです。したがって、値は 処理後に同じ文字列表現を持たない。また スクリプトに浮動小数点値を直接書き込むことを含む 数学的な操作なしで印刷します。

簡単な例:

$a = '36';
$b = '-35.99';
echo ($a + $b);

0.01を印刷すると思われますか? しかし、0.009999999999998のような非常に奇妙な答えが出力されます

他の数値と同様に、浮動小数点数doubleまたはfloatは、0と1の文字列としてメモリに保存されます。浮動小数点と整数の違いは、0と1を調べたいときに、それらをどのように解釈するかです。格納方法には多くの標準があります。

浮動小数点数は通常、左から右へ、符号ビット、指数フィールド、仮数または仮数としてコンピューターデータにパックされます。...

十分なスペースがないため、10進数は2進数で十分に表現されません。それで、uouは0.3 / 3333のように正確に1/3を表現できません...? 0.01を2進浮動小数点数として表現できないのは、同じ理由によるものです。 1/100は0.00000010100011110101110000 ..... 10100011110101110000の繰り返しです。

0.01 32ビット)。この場合、オペレーティングシステムは、表示どおりに印刷するか、より人間が読める方法で印刷するかを決定します。そのため、どのように表現したいかはマシンに依存します。ただし、さまざまな方法で言語レベルで保護できます。

結果をフォーマットする場合、echo number_format(0.009999999999998、2); 0.01が出力されます。

この場合、どのように読むべきか、どの程度の精度が必要かを指示するからです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top