浮点到 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 意外结果的主要内容,如果未能解决你的问题,请参考以下文章

php数据类型转换(转)

PHP数据类型转换 (转)

javascriptphp强制类型转换

C语言的浮点型怎么转换为整型?

Php中的强制转换详解

js类型转换-字符串转整型浮点型方法强制类型转换等