浮点到 int 类型转换的 PHP 意外结果
Posted
技术标签:
【中文标题】浮点到 int 类型转换的 PHP 意外结果【英文标题】:PHP unexpected result of float to int type cast 【发布时间】:2011-03-24 01:50:01 【问题描述】:我正在尝试将浮点数转换为 php 中的 int 值:
var_dump((int)(39.3 * 100.0)); //Returns 3929 but should be 3930!
var_dump((int)(39.2 * 100.0)); //Returns 3920
我可以使用 ceil 使其工作,但有人可以向我解释一下吗?
var_dump((int)ceil(39.3 * 100.0)); //Returns 3930
【问题讨论】:
一个简短的说明,希望您期待 3930,而不是 3939。 【参考方案1】:这是因为在基数 10 中具有有限表示的数字在 PHP 使用的浮点表示中可能有也可能没有精确表示。
见
>php -r "echo var_dump(sprintf('%.40F', 39.3 * 100.0));" 字符串(45)“3929.9999999999995452526491135358810424804688”由于int
总是将数字向下舍入,因此表示中的一个小错误会使强制转换将其向下舍入一个数字,而不是您所期望的。
考虑改用round
。
【讨论】:
你不应该使用String和round,bcmul函数是有目的的。【参考方案2】:你应该看看这个页面:http://php.net/manual/en/language.types.float.php。 它描述了使用浮点数的陷阱。
【讨论】:
另一个很好的参考表明这是大多数计算机语言的常见问题是en.wikipedia.org/wiki/Floating_point#Accuracy_problems【参考方案3】:// gives: int(3930)
var_dump(intval((39.3 * 100.0) . ''));
或者,用于函数:
function floatToInteger ($fValue)
return (intval(($fValue + 0) . ''));
// gives: int(3930)
var_dump(floatToInteger(39.3 * 100.0));
【讨论】:
【参考方案4】:这可能会迟到,但正确的做法如下:
(int) bcmul("39.3", "100.0"); // 3930
(int) bcmul("39.2", "100.0"); // 3920
对于处理浮点数的数字/计算,或任何涉及金钱交易的事情,你不应该直接使用乘法/除法+转换。
也请参考:
http://php.net/manual/en/book.bc.php
注意:我的答案中的转换只是将 String 转换为 Int,(您不需要这样做)
【讨论】:
注意:bcmul 期望字符串作为参数,并且会抛出严格类型的 TypeError。 @SzabolcsPáll 感谢您的更正,在撰写本文时 PHP 5 仍然占主导地位,但您的评论在所有情况下都有效以上是关于浮点到 int 类型转换的 PHP 意外结果的主要内容,如果未能解决你的问题,请参考以下文章