2013-10-02 79 views
0

我有一个项目,存储在bigint列在数据库中的钱(存储在美分)。我打算重写这个东西来代替使用BCMATH。我不介意整数,但他们给我一些存储在美分中的可怕四舍五入错误事件,我怀疑我可能在BCMATH中有相同的舍入错误。问题出现在的情况下,想在这个伪代码:PHP的钱计算精度

$price = $some_price_in_cents * $store_price_increase; // second value is a float for final price calculation, so the result might have fractions of a cent 
$price_total = $price * $qty; 
$discount = // some discount in cents (might have fractions of a cent) 
$discount *= $qty; 
$discounted_price = $price_total - $discount; 

当插入到数据库中,我做轮()在仙的所有值。现在,我有说,一个记录:

total price = 12134 
discount = 460 
discounted price = 11675 

现在,如果我做12134 - 460 ......我明明得到11674,而不是11675. 我也怀疑,如果我改变了事情的计算方法(如:我会得到不同的结果。

我会用BCMATH得到这种行为吗?结果会取决于数学运算的顺序吗?我如何正确计算上述使用BCMATH并将其存储在数据库中(假设需要2个小数位)?

+1

我建议使用DECIMAL数据类型来存储钱。 –

+0

除非您溢出整数(在32位上为> = 2^31或在64位上为2^63),并且除非正在执行分割,否则不能使用整数算术产生错误。 'round()'实际上[返回一个浮点数](http://php.net/manual/fr/function.round.php),我怀疑你实际上在某些时候不知道使用浮点数。我个人将所有金额存储在数据库中,使用整数列;这是非常安全的,并且适用于多种货币('DECIMAL'具有固定的精度)。将货币作为整数(以次要单位)与货币代码一起存储可解决问题。 – Benjamin

+0

关于你的钱操作,我建议你使用一个合适的[PHP Money库](https://github.com/brick/money)(免责声明:我创作了这个)。这款产品使用纯粹的PHP,GMP或BCMath,基于可用的内容,并确保对任何规模的资金进行安全计算。另外,您可以将货币转换为整数并将其转换为整数,以将其安全地存储在数据库中。 – Benjamin

回答

1

我相信这是你需要的。请注意,bcmath需要字符串。数字2是指定你需要多少小数。

$price = bcmul($some_price_in_cents, $store_price_increase, 2); 
$price_total = bcmul($price, $qty, 2); 
$discount = bcmul($qty, "discount amount", 2); 
$discounted_price = bcsub($price_total, $discount, 2);