0

私は通貨入力を扱っています。小数点以下 2 桁のみを使用してください。入力を float にキャストして 100 を掛けてみました。これは、誰かが小数点の後に 2 桁以上入力するまで問題なく動作します。

// Returns 6999.8 instead of 6999
$cents = floatval('69.998') * 100;

次に、結果を int にキャストしようとしたため、小数点以下の連続した数字は無視されます。上記の問題は解決しますが ('69.998' は 6999 になります)、浮動小数点から整数への変換を使用して新しい問題を作成します。

// Returns 6998 instead of 6999
$cents = intval(floatval('69.99') * 100);

floor() も検討しましたが、intval() と同じフロートの問題を引き起こします。

これは私が使用することを考えているものです:

$cents = intval((string)(floatval('69.99') * 100));

どちらの場合も機能しますが、ハックのように感じられ、遅くて頭が痛いので、ここで明らかな何かが欠けている可能性があります. これを行うより良い方法はありますか?

4

4 に答える 4

4

$cents = intval(round(floatval('69.99') * 100));

何が必要?

精度も指定できます。たとえば、あなたのケースでは、オリジナルを小数点以下 2 桁に四捨五入したいとおっしゃいました。

$twodecimal = round(floatval('69.998'),2);//returns a float representation of 70

これらのドキュメントの大きな赤い通知を必ず確認してください

于 2012-11-06T20:40:04.957 に答える
2

これ69.99 * 100は、の浮動小数点表現があるためです6998.9999999*(オフ:javascriptコンソールでも確認できます)。正確にしたい場合は、 BCMathのようにphp拡張子の付いた固定小数点数を使用する必要があります。または、この特定の問題に対して単純な正規表現を記述できます。

$amount = '69.99';

if (preg_match('/^(-?\d+)(\.(\d{1,2}))?/', $amount, $matches))
{
    $amount = (int) ($matches[1] . (isset($matches[3]) ? str_pad($matches[3], 2, '0') : '00'));
}
else
{
    $amount = ((int) $amount) * 100;
}
于 2012-11-06T21:13:45.270 に答える
0
$cents = intval(round(floatval('69.99') * 100));

これにより、最も近い数値が正しく取得されます。これは、69.99おそらくメモリ内で次のように表されるため、浮動ポインターの精度の問題が原因です。69.9899999

intval小数の残りの部分を切り捨てるだけなので、 に69.989999 * 100なり6998.9999、切り捨てられます6998

于 2012-11-06T20:42:21.647 に答える
0

整数を使用して通貨値を含めることをお勧めします。float を使用すると、すぐに丸め誤差が発生する可能性があります。

私が見たアプリケーションでは、小数点を想定した整数が使用されています。すべての値は、米ドルのセントやユーロなど、最も近い通貨単位に保持されます。小数点のない通貨もあれば、小数点以下 2 桁ではなく 3 桁の通貨もあります。

小数点以下の桁数を想定して整数を操作することで、浮動小数点で見られる丸め誤差やその他の問題を大幅に減らすことができます。

変換を行うには、文字列操作を使用し、文字列操作で小数点を削除し、必要な桁数だけが入力されていることを確認することをお勧めします。

于 2012-11-06T20:44:46.677 に答える