php float計算2小数点
-
05-07-2019 - |
質問
別の数学計算の問題をもう一度取得します。
$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が出力されます。
この場合、どのように読むべきか、どの程度の精度が必要かを指示するからです。