我正在使用货币输入。应使用小数点后仅两位数。我尝试将输入转换为浮动并乘以100,这可以正常工作,直到有人在十进制标记后输入两位数以上:
// 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));
它适用于两种情况,但感觉就像一个黑客,它已经很晚了,我的头疼,所以也许我错过了一些明显的东西。有更好的方法吗?
答案 0 :(得分:4)
是
$cents = intval(round(floatval('69.99') * 100));
你需要什么?
您还可以指定精度。例如,在您提到的情况下,您提到要将原始数据舍入到两位小数:
$twodecimal = round(floatval('69.998'),2);//returns a float representation of 70
请务必查看这些docs
中的大红色通知答案 1 :(得分:2)
这是因为69.99 * 100
的{{3}}代表6998.9999999*
(关闭:您也可以在javascript控制台上查看)。如果你想要准确,你应该使用带有php扩展名的floating-point号码,例如fixed-point - 或者,你可以为这个特定问题写一个简单的正则表达式
$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;
}
答案 2 :(得分:0)
$cents = intval(round(floatval('69.99') * 100));
这会正确地得到最接近的数字,这是因为浮动指针精度问题,因为69.99
可能在内存中表示为69.9899999
intval
只会截断小数的其余部分,因此69.989999 * 100
变为6998.9999
并被截断为6998
答案 3 :(得分:0)
我建议您使用整数来包含货币值。使用浮动可能会迅速导致舍入错误。
在我看过的应用程序中,使用带有假定小数点的整数。所有价值均以最接近的货币单位计算,例如美元或欧元的分数。有些货币没有小数点,并且有一些货币而不是两个小数位有三个小数位。
通过使用带有假定小数位的整数进行操作,您可以真正减少舍入误差和浮点可以看到的其他问题。
要进行转换,我建议使用字符串操作并使用字符串操作删除小数点,并执行检查以确保只输入所需数量的位置。