PHP强制将float转换为string,将其强制转换为int

时间:2019-01-17 15:46:49

标签: php

您不希望看到的东西,但是需要知道何时在php中处理浮点数

<?php


    $i = (32.87*100);

    echo $i;                 // outputs 3287
    echo (int) $i;           // outputs 3286 !!
    echo (int) (string) $i   // outputs 3287 

$i的内部表示类似于3286.9999999。

为什么$i 3287是字符串表示形式?

2 个答案:

答案 0 :(得分:3)

让我们看一下您的代码:

$i = (32.87*100);

现在$i的浮点数略小于3287,如下所示:

echo sprintf('%.30f', $i) . PHP_EOL; //3286.999999999999545252649113535881

但是,当您打印(回显)它时,您将获得四舍五入的值。

echo $i;                 // outputs 3287

在这里我们要诀窍-将float转换为int意味着尽管点.99999999(...)几乎等于1(但不是!),但仅将点后的部分切除。因此输出为3286。

echo (int) $i;           // outputs 3286 !!

现在,在最后一个示例中,您首先将float转换为字符串,这意味着您已经通过执行echo $i;来完成操作,因为无论打印什么,内部都需要PHP转换为字符串。因此,将其3286.999999999999545252649113535881强制转换为"3287",然后强制转换为3287,然后打印。

echo (int) (string) $i   // outputs 3287;

总而言之,将float转换为string和int的方式有所不同。

EDIT关于“取整”的进一步说明

不是真正的四舍五入。那样说我犯了一个错误。

PHP使用64位浮点数(称为 double ),以十进制表示时具有14位精度。

PHP manual中所述:

  

浮点数的大小取决于平台,尽管通常值(64位IEEE格式)的最大值约为1.8e308,精度约为14个十进制数字。

这意味着,浮点数可以(在大多数情况下)包含14位数字(十进制),而点的位置无关紧要。

现在,最重要的是:

强制转换为字符串不能舍入浮点数

示例:

  • $a = 1.23456789012349-最后一个9是第15位数字,因此您将获得“四舍五入”的浮点数到1.2345678901235
  • $a = 12345678901234.9-与上面相同
  • $a = 1.99999999999999-最后一个9是第15位数字,因此您将获得2

作为字符串,它将完全按照浮点数进行打印,这意味着14位精度。 “舍入”是在内存中创建float变量的结构的那一刻。

最后一个例子是我们在本主题中讨论的内容。

现在,为什么我犯了这个错误并谈到“四舍五入”? 我误解了echo sprintf('%.30f', $i)的结果。 A看到了更多的数字,并认为这是浮点数的真实值。

但不是。

我们知道,64位浮点数只有14位精度。

那么sprintf的结果来自哪里?

答案实际上很简单。

我们已经知道,在二进制系统中并不总是能够表示十进制数。因此,例如,一个简单的0.1浮点数(二进制表示形式)只是一个近似值,因为实际的二进制表示形式将无限长。

现在,将二进制系统转换为十进制时,它的工作原理完全相同。可以用二进制(表示每个浮点值)表示的内容,但并非总是可以用十进制表示的。

因此sprintf('%.30f', $i)给出的是将浮点数从二进制转换为十进制的30位精度近似值。

感谢@ Quasimodo'sclone在评论中要求对此进行更精确的介绍。这使我对这个话题更加深入。

答案 1 :(得分:0)

您要将$i(3287)转换为字符串,然后转换为int,因此结果保留为3287。 如果将$i转换为一个整数,则将获得3286,然后如果将其转换为一个字符串,则将具有所需的内容。

尝试echo (string) (int) $i