문제

I have a simple piece of code as below.

$amount = 447274.44882;
$rate = 0.00001;

echo floatNumber(bcmul($amount, $rate, 8), 8);

This outputs 0.00000000 when it should be 4.47274449. If I change the rate to 0.0001 then it outputs the correct number, anything higher than 4 decimals and it reports 0.

Am I doing something wrong or is this a known limitation or something? Seems quite a big one if that's the case.

도움이 되었습니까?

해결책

If you cast 0.00001 to string using the default settings (and that's what will happen if you feed bcmul with floats since it expects strings) you'll get this:

var_dump( (string)0.00001 );
string(6) "1.0E-5"

It isn't clearly documented but bcmath functions apparently return cast to zero when faced to invalid input:

var_dump( bcadd('Hello', 'world!', 8) );
var_dump( bcadd('33', 'Foo', 8) );
var_dump( bcdiv('33', 'Foo', 8) );
string(10) "0.00000000"
string(11) "33.00000000"
Warning: bcdiv(): Division by zero
NULL

The whole idea of arbitrary precision libraries is to overcome the limitations of base 2 arithmetic and fixed size storage. Thus you'd need this:

var_dump( bcmul('447274.44882', '0.00001', 8) );
string(10) "4.47274448"

This is great to do math with 100-digit numbers but not particularly useful for simple rounding. In fact, the extension doesn't round at all—it merely truncates:

var_dump( bcmul('20.01', '1.444', 3) );
var_dump( bcmul('20.01', '1.444', 2) );
var_dump( bcmul('20.01', '1.444', 1) );
var_dump( bcmul('20.01', '1.444', 0) );
string(6) "28.894"
string(5) "28.89"
string(4) "28.8"
string(2) "28"
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top