本文介绍了为什么两个具有PHP_INT_MAX值的float变量是相同的,除非添加其中一个值大于1025的变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<?php
$x=PHP_INT_MAX;
echo ((float)($x+1026)==(float)($x))?'EQUAL':'Not Equal';

我知道浮点运算并不精确,并且$ x和$ x + 1如此接近,以致它们四舍五入为相同的浮点值,并且如果使用1到1025之间的任何数字,则输出将显示为EQUAL,但是仅当您使用超过1025的值后,它才会开始输出为不等于".我想知道为什么吗?背后的原因是什么?为什么只在1025年之后?

I know floating point arithmetic is not exact and $x and $x+1 are so close together that they are rounded to the same floating point value and it shows the output as EQUAL if you use any number between 1 and 1025 but its only after you use value beyond 1025 it will start giving output as 'Not Equal'. I want to know why? What's the reason behind it? Why only after 1025?

推荐答案

对于浮点型,您的假设 $ x == $ x + 1 不一定是真的:

With float, your assumption $x == $x + 1 is not necessarily true:

$x=2;
echo ((float)($x+1)==(float)($x))?'EQUAL':'Not Equal';

产生不相等".

在注释中链接的转换器中( http://www.h-schmidt.net/FloatConverter/IEEE754.html ),则可以重现此内容.十进制 2.0 产生 0x40000000 ,十进制 3.0 产生 0x40400000 ,因此在IEEE754浮点数上它们确实有所不同表示形式.

In the converter linked in the comments (http://www.h-schmidt.net/FloatConverter/IEEE754.html), you can reproduce this. decimal 2.0 yields 0x40000000, decimal 3.0 yields 0x40400000, so they're indeed different when it comes to IEEE754 float representation.

例如,十进制 0.1 不能表示为float: 0x3dcccccd ,即 0.10000000149011612 .

Whereas, e.g., decimal 0.1 cannot be represented as float: 0x3dcccccd, which is 0.10000000149011612.

什么是十进制 9223372036854775807 ?那是 0x5f000000 ,它是 9.223372E18 ,它是 9223372180000000000 .

What's decimal 9223372036854775807? That's 0x5f000000, which is 9.223372E18, which is 9223372180000000000.

什么是十进制 9223372036854775808 ( PHP_MAX_INT + 1 )?那也是 0x5f000000 .

What's decimal 9223372036854775808 (PHP_MAX_INT + 1)? That's 0x5f000000, too.

什么是十进制 9223372036854776832 ( PHP_MAX_INT + 1025 )?那也是 0x5f000000 .

What's decimal 9223372036854776832 (PHP_MAX_INT + 1025)? That's 0x5f000000, too.

什么是十进制 9223372036854776833 ( PHP_MAX_INT + 1026 )?那也是 0x5f000000 .

What's decimal 9223372036854776833 (PHP_MAX_INT + 1026)? That's 0x5f000000, too.

他们都是一样的.

例如,十进制 9223373000000000000 ( PHP_MAX_INT + 963145224193 )?那是 0x5f000001 ,它是 9.223373E18 ,它是 9223373000000000000 .

Whereas, e.g.: decimal 9223373000000000000 (PHP_MAX_INT + 963145224193)? That's 0x5f000001, which is 9.223373E18, which is 9223373000000000000.

现在,为什么:

((float)($x+1025)==(float)($x+1026))?'EQUAL':'Not Equal';

是否产生不等于"?

您正在向 PHP_MAX_INT 添加一个整数.

You're adding an integer to PHP_MAX_INT.

$x=PHP_INT_MAX;
$y=PHP_INT_MAX-1;
$z=PHP_INT_MAX+1;
var_dump($x);
var_dump($y);
var_dump($z);

产量:

int(9223372036854775807)
int(9223372036854775806)
float(9.2233720368548E+18)

PHP隐式地转换太大而无法浮动的整数.那就是您基本上迷失在PHP内部的地方(至少在我看来),因为从这里开始,您将永远不会知道会发生什么(尽管不了解PHP内部,但是随时可以纠正我).

PHP implicitly converts integers too large to float. And that's where you're basically lost in PHP internals (at least in my opinion), because from here, you'll never know what will happen (without knowing PHP internals, feel free to correct me, though).

请注意:

$x=PHP_INT_MAX;
$a=(float)($x+1025.0); // 1025 float
$b=(float)($x+1026.0); // 1026 float
$c=(float)($x+1025); // 1025 int
$d=(float)($x+1026); // 1026 int
var_dump($x);
var_dump($a);
var_dump($b);
var_dump($c);
var_dump($d);
var_dump($a==$b);
var_dump($a===$b);
var_dump($c==$d);
var_dump($c===$d);

产量:

int(9223372036854775807)
float(9.2233720368548E+18)
float(9.2233720368548E+18)
float(9.2233720368548E+18)
float(9.2233720368548E+18)
bool(true)
bool(true)
bool(false)
bool(false)

如果将整数( $ x + 1026 )添加到 PHP_MAX_INT ,则该整数将转换为float,并且当您添加float( $ x +1026.0 ),它当然也是浮动的.但是,显然,它们在内部并不相同,请参见上面的比较.

If you add an integer ($x+1026) to PHP_MAX_INT, it is converted to float, and when you add a float ($x+1026.0), it is float, too, of course. But, obviously, they're not the same internally, see the comparisons above.

底线:

  • 不要比较浮点数是否相等
  • 请小心您的演员表;(float)($ x + 1026)是整数加法,然后转换为float,而(float)($ x + 1026.0)转换 $ x进行浮动,然后添加浮动 1026.0 ,然后(多余)强制转换为float.
  • Don't compare floats for equality
  • Be careful about your casts; (float)($x+1026) is an integer addition, and afterwards casted to float, whereas (float)($x+1026.0) converts $x to float, then adds the float 1026.0, then casts (superfluously) to float.

此外,请参见:

这篇关于为什么两个具有PHP_INT_MAX值的float变量是相同的,除非添加其中一个值大于1025的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 00:01