可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Boy, this one is really weird. I expect the following code to print 1990, but it prints 1989!
$val = '$19.9'; $val = preg_replace('/[^\d.]/','',$val); $val = intval($val * 100); echo $val;
Why on earth is this happening?
Edit: and this code:
$val = '$19.9'; $val = preg_replace('/[^\d.]/','',$val); echo $val . "
"; $val = $val * 100; echo $val . "
"; $val = intval($val); echo $val;
Prints:
19.9 1990 1989
Why does intval(1990)
equal 1989
???
回答1:
This is a precision issue inherent to floating point numbers in PHP, and lots of other languages. This bug report discusses it a bit, in the context of casting as an int:
http://bugs.php.net/bug.php?id=33731
Try round($val * 100)
instead.
回答2:
回答3:
Why does intval(1990) equal 1989???
Because you're not taking intval(1990)
. You're taking intval($val * 100)
where $val
is a number close to, but slightly smaller than, 19.9.
Read The Floating-Point Guide to understand why this is so.
As for how to fix it: don't ever use floating-point values for money. In PHP, you should use BCMath instead.
回答4:
$val
is a floating point number - the result of "19.9" * 100
. Floating point numbers are not 100% accurate in any language (this is by design). If you need 100% decimal accuracy for dollar values, you should use integers and perform all calculations using cents (E.g., "$19.90"
should be 1990
).