为什么我从数组中获得的负值与设置的值不同?

时间:2018-11-07 17:22:02

标签: php arrays

我对一个功能进行了一系列测试:

        $testArray = array(
            (object)array(
                "value"     => 12345678901,
                "expected"  => "123456789012"
            ),
            (object)array(
                "value"     => "1234567890",
                "expected"  => false
            ),
            (object)array(
                "value"     => (int)12345678901,
                "expected"  => "123456789012"
            ),
            (object)array(
                "value"     => 1234567890,
                "expected"  => false
            ),
            (object)array(
                "value"     => "12345678901",

                "expected"  => "123456789012"
            ),
            (object)array(
                "value"     => "123456789012",
                "expected"  => "123456789012"
            ),
            (object)array(
                "value"     => "123456789013",
                "expected"  => false
            ),
            (object)array(
                "value"     => "1234567890128",
                "expected"  => "1234567890128"
            ),
            (object)array(
                "value"     => "1234567890127",
                "expected"  => false
            ),
            (object)array(
                "value"     => array(),
                "expected"  => false
            ),
            (object)array(
                "value"     => (object)array(),
                "expected"  => false
            ),
            (object)array(
                "value"     => array("1234567890127"),
                "expected"  => false
            ),
            (object)array(
                "value"     => (object)array("1234567890127"),
                "expected"  => false
            )
        );

我通过一个foreach循环运行该数组,以查看哪些可以测试一个函数,并且大多数可以正常工作。第三个应该返回123456789012,但是当我得到该值时,它将返回“ -539222987”。其余的一切正常时,为什么会发生这种情况?

这是foreach循环。 validUPC函数仅查看upc并确保它是有效的。

        foreach($testArray as $key => $test) { // Test each value
            $result = App::make("Product")->validUPC($test->value);
            var_dump($result);
            echo "Result from array member $key was: $result\n";
            if($result !== $test->expected) { // Check against expected value
               echo "Test FAILED\n";
               $success = false; // Returns false if any of them failed
            }
            else {
               echo "Test passed\n";
            }
        }

validUPC函数开始如下:

public function validUPC($upc = "non") {
    try {
        // If there is no upc specified, get the product upc
        if($upc == "non") {
            $upc = $this->upc;
        }
        // No arrays allowed
        if(is_array($upc)) {
            return false;
        }
        // Make it a string
        $upc = (string)$upc;
        var_dump($upc);

哪个返回如下:

Product.php:99:float 12345678901
Product.php:101:string '12345678901' (length=11)
CatalogTest.php:70:string '123456789012' (length=12)
Result from array member 0 was: 123456789012 Test passed
Product.php:99:string '1234567890' (length=10)
Product.php:101:string '1234567890' (length=10)
CatalogTest.php:70:boolean false
Result from array member 1 was: Test passed
Product.php:99:int -539222987
Product.php:101:string '-539222987' (length=10)
CatalogTest.php:70:boolean false
Result from array member 2 was: Test FAILED

1 个答案:

答案 0 :(得分:3)

我没有详细查看代码,我推测。

在32位平台上,最大可表示整数是2 31 -1或2,147,483,647。您提供的整数-123456789012-大于该整数。与其他语言一样,当您提供一个大于最大值的整数时,PHP会将数字溢出为它可以表示的值。您的情况是-539222987。

我建议您检查您的代码是否不尝试在平台上使用大于PHP_INT_MAX的整数。


响应评论:PHP将大于可用位可表示的整数转换为双精度型。但是,如果您随后将 that 转换为一个整数,则输入看起来像是环绕的东西。在64位系统上,例如:

$a = pow(2, 65); // 65 === (PHP_INT_SIZE * 8) + 1
var_dump($a);
$b = (int)$a;
var_dump($b);
$c = $b - 100;
var_dump($c);

在数学上,我们期望$ c === 36893488147419103132。输出为:

float(3.6893488147419E+19)
int(0)
int(-100)

浮点数近似等于精确值:我们已经在低位中交换了精度,以便能够继续使用数值作为数字。但是,当我们强制PHP将其视为整数时,它会放弃并将其截断为0-但行为是不确定的,因此不要一直依赖于它完全是0:点。

更糟糕的是,没有警告,没有任何通知。那么,如何在这种情况下保护代码?我敦促使用strict_types。当您期望精确地使用int时,请定义函数以使用它们。如果您随后计算出一个上溢或下溢的值,则会得到一个浮点数,该浮点数将传递到严格的int方法中,然后 会通知您。

如果您需要使用大整数,there are libraries for that.