2012-11-06 132 views
0

我正在使用货币输入。应使用小数点后两位数字。我试着输入铸造浮动和100,直到有人进入小数关口后超过两位数的正常工作相乘:消毒货币输入

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

然后我试图铸造结果为int,所以小数点后连续数字被忽略。它解决了上述问题('69 0.998' 变为6999),但创建一个具有浮动一个新的整数转换:

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

我也算是地板(),但它触发同样的浮动问题,因为INTVAL()。

这是我在考虑使用:

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

它工作在这两种情况下,但感觉就像一个黑客攻击和它的晚,我的头很痛,所以也许我缺少的东西在这里很明显。有一个更好的方法吗?

+1

你为什么不只是四舍五入到最接近乘以100后的数字? –

回答

3

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

你需要什么?

您还可以指定精度。例如,你的情况,你提到你想原来四舍五入至小数点后两位:

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

一定要在这些docs

+0

谢谢,四舍五入的浮动价值很好,现在(在早上)似乎很明显。 – arnaslu

+0

我正在使用的规范实际上要求在小数点后两位忽略数字,所以舍入输入本身在这种情况下不起作用。 – arnaslu

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

这将看看大红色通告这是因为浮点指针精度问题,因为69.99可能在内存中表示为69.9899999

intval只是截断了r因此69.989999 * 100变为6998.9999并被截断为6998

0

我建议您使用整数来包含货币值。使用浮点数可能会导致舍入误差。

在我看到的应用程序中,整数与假定的小数点一起使用。所有的价值都保持到最接近的货币单位,例如美元或欧元。有货币没有小数点,有一对夫妇,而不是小数点后两位有三位小数。

通过使用具有假定小数位的整数进行操作,可以真正减少舍入错误和其他浮点可以看到的问题。

要进行转换,我建议使用字符串操作并删除字符串操作的小数点以及执行检查以确保只输入所需数量的位置。

2

这是因为69.99 * 100floating-point代表6998.9999999*(关闭:你也可以在javascript控制台中检查它)。如果你想成为精确的,你应该使用一个fixed-point号码与PHP扩展,像BCMath - 或者,你可以写一个简单的正则表达式为这一特定问题

$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; 
} 
+0

我知道浮点的缺点,这就是为什么我将值转换为分,所以我可以使用整数。感谢BCMath的链接,从未听说过它。 – arnaslu