我对一个功能进行了一系列测试:
$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
答案 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.