Why does `intval(19.9 * 100)` equal `1989`?

匿名 (未验证) 提交于 2019-12-03 02:00:02

问题:

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:

The usual answer to this kind of question is to read What Every Computer Scientist Should Know About Floating-Point Arithmetic.



回答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).



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!