2013-10-02 3 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; 

데이터베이스에 삽입, 내가 센트의 모든 값에() 라운드 않습니다. 내가 분명히 나는 ​​또한 의심 11,674하지 11675. 좀 .. (460)이 내가 (물건을 계산하는 방법을 변경 한 경우 예 -

total price = 12134 
discount = 460 
discounted price = 11675 

을 지금은 12,134을 할 경우 : 그리고 지금 나는라는 기록이있다. 마지막에 QTY로 모든 것을 곱하십시오), 나는 다른 결과를 얻을 것입니다.

BCMATH를 사용하면 이러한 종류의 동작이 발생합니까? 그 결과는 수학 연산의 순서에 달려 있습니까? 위의 BCMATH를 사용하여 위의 내용을 올바르게 계산하고 DB에 저장하려면 어떻게해야합니까? (소수 2 자리 필요)?

+1

돈을 저축하기 위해 DECIMAL 데이터 형식을 사용하는 것이 좋습니다. –

+0

32 비트에서 2^31 이상, 64 비트에서 2^63 이상의 정수가 넘는 경우가 아니면 나누기를 수행하지 않는 한 정수 연산을 사용하여 오류가 발생할 수 없습니다. 'round()'는 사실 [float을 반환합니다] (http://php.net/manual/fr/function.round.php), 여러분은 어떤 시점에서 실제로 플로트를 사용하고 있었다고 생각합니다. 저는 개인적으로 모든 돈을 정수 열을 사용하여 데이터베이스에 센트로 저장합니다. 이것은 완벽하게 안전하며 여러 통화로 잘 작동합니다 ('DECIMAL'은 고정 된 정밀도를가집니다). 통화 코드와 함께 정수로 마이너 단위로 돈을 저장하면 문제가 해결됩니다. – Benjamin

+0

돈 운영에 관해서는 적절한 [PHP Money 라이브러리] (https://github.com/brick/money)를 사용하는 것이 좋습니다 (면책 조항 : 저는이 저작물을 저술했습니다). 이 제품은 사용 가능한 PHP4, GMP 또는 BCMath를 사용하며, 어떤 크기의 돈이라도 안전하게 계산할 수 있습니다. 또한 Money를 정수로 변환하거나 변환하여 데이터베이스에 안전하게 저장할 수 있습니다. – 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);