-0 不等于 0

4

我有一个计算值的函数,该值是浮点型:

function crunch (float $a, float $b):float
{
  //do stuff
  return $result;
}

function testSomething (float $a, float $b):bool
{
  //if $result is -0 that returns false
  $result = crunch($a, $b);
  return $result === 0;
}

为什么-0不等于0,如何安全地检查该数字是否为零,假设0应该与-0相同? 更新 由于有更多细节的问题。我有一个名为Vec2的类,它具有x()y() getter,以及一个名为cross的方法,它看起来像这样:
public function cross(Vec2 $vec2):float
{
  return ($this->_x * $vec2->_y) - ($vec2->_x * $this->_y);
}

运行以下代码:

$cross = $this->cross($d);

这导致调试器输出如下:

enter image description here

$cross === 0的评估结果为false


1
你能详细解释一下结果是如何生成或者看起来是什么样子的吗?-0不是一个东西,这是真的:var_dump(-0 === 0); - ChristianM
return $result === 0.; 这个怎么样? - Xorifelse
2
是的,我正想说,0 是 int 类型而不是 float :D 你需要使用 (float)0 进行比较。 - ChristianM
这是否意味着浮点数零和整数零是不同的,即使它们表示相同的数量:什么都没有? - philipp
2
我喜欢 PHP!我会一直使用它! - philipp
显示剩余10条评论
3个回答

5

将0转换为浮点数。可能失败的原因是,0作为字面值是整数,而结果是浮点数,因此由于类型不同,===返回false。

至少做类似这样的事情,像您的情况一样失败(结果为false):

php -r '$a = (float) -0; $b = 0; echo ($a === $b);'

在此情况下,结果为真:
php -r '$a = (float) -0; $b = (float) 0; echo ($a == $b);'

我更喜欢短语法而不是类型转换。0. - Xorifelse
$floatvalue === 0. evaluates to true! All the attention to the . at the and end. - philipp
没错。我更喜欢0.0或0.00,我认为这样阅读起来更自然。 - monstercode
当然,.0 也是可以的。它只是一个定义好的浮点数。在将浮点数进行字符串拼接时要小心。 - Xorifelse

4
  1. 负零不是一个实际存在的概念。但是在浮点数显示的精度限制下,有可能出现一个比零小的负值。
  2. 你不能可靠地检查两个浮点数之间的直接等价性,你只能合理地检查两个浮点数之间的差异是否小于在给定计算中所关心的精度。
function float_equiv(float $a, float $b, float $epsilon=NULL) {
    // default to PHP's configured display precision
    $epsilon = $epsilon ?: pow(10, -1*ini_get('precision'));

    if( abs($a - $b) < $epsilon ) {
        return true;
    }
    return false;
}

“precsion” 可能是一个打字错误,应该是 “precision”,不是吗? - Funk Forty Niner
第三次是成功的。 - Sammitch
^ 那就是它 ;-) - Funk Forty Niner
测试不错,但它涉及类型转换,而0.与仅为0在PHP逻辑中是完全不同的。 - philipp

0

仅仅是为了说明@monstercode所接受的答案

数学逻辑和计算机逻辑是分开的实体。 我们直观地知道-0 = 0,但在计算机术语中,数字的符号与数字本身是分开存储的(就像元数据)- 这就是浮点数的作用。

在这种情况下,一个整数被与一个浮点数进行比较。

$result_1 = 1234*0;// remains an integer
$result_2 = -1234*0;// remains an integer

$result_3 = -1.234*0;// becomes a float
$result_4 = 1.234*0; // becomes a float

var_dump($result_1 === 0); // true
var_dump($result_2 === 0); // true

var_dump($result_3 === 0); // false
var_dump($result_4 === 0); // false

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接