1

我试图将我的美元金额转换为美分,但每次都会减少一美分。不使用任何 php 扩展的最佳方法是什么?

$amount = 129.95;

$amountInCents = intval(floatval($amount) * 100);

echo $amountInCents; //output: 12994
4

3 回答 3

4

由于浮点运算和值存储的不准确性(http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html),浮点数不能准确表示很多值,例如 129.95 - in在这种情况下,它类似于 129.9499999,因为它不能完全存储 192.95。

因此,当您使用 intval 向下舍入时,它会看到您有 12994.999... 并向下舍入为 12994。

要解决这个问题,您可以尝试

1)如果您将美元和美分金额作为字符串,例如"$129.95",使用字符串解析将美元和美分计算为整数

2) 在将浮点值转换为 int 之前添加一个非常小的值,例如 0.00001

3) 在使用 intval 之前使用round http://php.net/manual/en/function.round.php以便将其四舍五入到最接近的整数。

于 2013-06-14T02:53:15.120 回答
4
$amount = 129.95;
echo (string)(floatval($amount) * 100); // cast it to string
于 2013-06-14T03:00:41.820 回答
1

并非所有数字都可以用浮点数表示。这很明显,因为(例如)只有 2 64 个可能的 64 位值(实际值较少,因为编码需要诸如 NaN 和无穷大之类的东西),但浮点数是无限的。

请参阅此答案以获取更多说明。

所以像这样的数字129.95实际上可能是这样129.949999999923234的,当你锻炼时intval(val * 100),你最终会得到12994.

一种解决方案是对数字进行入而不是截断,大多数语言都会为您提供多种方法来做到这一点。或者,您可以使用以下方法模拟它:

intval(val * 100 + 0.5);

或者,您可以通过不使用 IEEE754 浮点数来避免它们的问题。现在整数类型可能已经足够大了,您可以直接存储整数美分,而不会发生此类错误(根据计算的复杂性,可能还有其他错误,但它们几乎肯定会小于浮点数观点)。

而且,如果您需要更大的范围,您可能必须选择 BigInteger 类型的包。

于 2013-06-14T02:59:10.183 回答