array_unique具有SORT_NUMBERIC行为



我偶然发现了一些奇怪的东西,我不明白为什么它会这样工作。

我有一个数字数组,它们都是唯一的:

$array = [
98602142989816970,
98602142989816971,
98602142989816980,
98602142989816981,
98602142989816982,
98602142989816983,
98602142989820095,
98602142989820096,
98602142989822060,
98602142989822061,
];
var_dump($array);
array(10) {
[0]=>
int(98602142989816970)
[1]=>
int(98602142989816971)
[2]=>
int(98602142989816980)
[3]=>
int(98602142989816981)
[4]=>
int(98602142989816982)
[5]=>
int(98602142989816983)
[6]=>
int(98602142989820095)
[7]=>
int(98602142989820096)
[8]=>
int(98602142989822060)
[9]=>
int(98602142989822061)
}

如果我做print_r(array_unique($array));,一切都很好,我得到:

Array
(
[0] => 98602142989816970
[1] => 98602142989816971
[2] => 98602142989816980
[3] => 98602142989816981
[4] => 98602142989816982
[5] => 98602142989816983
[6] => 98602142989820095
[7] => 98602142989820096
[8] => 98602142989822060
[9] => 98602142989822061
)

但如果我添加SORT_NUMERIC标志print_r(array_unique($array, SORT_NUMERIC));,我得到:

Array
(
[0] => 98602142989816970
[6] => 98602142989820095
[8] => 98602142989822060
)

为什么只返回这3个数字?

更新:我使用的是64位系统。

对于sort函数,我手动打乱了一些值,因为在原始数组中它们已经排序了。

如果我执行sort($array);,则响应如预期:

Array
(
[0] => 98602142989816970
[1] => 98602142989816971
[2] => 98602142989816980
[3] => 98602142989816981
[4] => 98602142989816982
[5] => 98602142989816983
[6] => 98602142989820095
[7] => 98602142989820096
[8] => 98602142989822060
[9] => 98602142989822061
)

但对于sort($array, SORT_NUMERIC);,它们的排序不正确:

Array
(
[0] => 98602142989816970
[1] => 98602142989816982
[2] => 98602142989816983
[3] => 98602142989816980
[4] => 98602142989816981
[5] => 98602142989816971
[6] => 98602142989820095
[7] => 98602142989820096
[8] => 98602142989822060
[9] => 98602142989822061
)

您遇到了这样规模的精度和浮点运算问题。浮点数学坏了吗?如果你感兴趣的话,但我不认为这是重复的。

取你的前两个号码:

php > var_dump((float) 98602142989816970 === (float) 98602142989816971);
bool(true)
php > var_dump((float) 98602142989816970, (float) 98602142989816971);
float(9.8602142989817E+16)
float(9.8602142989817E+16)

在内部,当PHP在numeric_compare_function中使用SORT_NUMERIC比较数组中的值时,就会发生这种情况。

sort也遇到同样的问题,请参阅https://3v4l.org/02UUB(显然,没有从数组中删除任何值,因为这只发生在array_unique中——它们只是没有正确排序(

简言之,对于这种大小的数字(或者特别是相对于其规模非常接近的数字(,SORT_NUMERIC将不可靠。如果可以的话,坚持把它们作为字符串进行比较。

无论代码是在32位PHP还是64位版本下运行,都会有所不同,因为那里的整数也有32位或64位长。

$array = [
98602142989816970,
98602142989816971,
98602142989816980,
98602142989816981,
98602142989816982,
98602142989816983,
98602142989820095,
98602142989820096,
98602142989822060,
98602142989822061,
];
echo '<pre>';
var_dump(PHP_INT_MAX,$array);

32位系统的结果:

int(2147483647)
array(10) {
[0]=>
float(9.8602142989817E+16)
[1]=>
float(9.8602142989817E+16)
[2]=>
float(9.8602142989817E+16)
[3]=>
float(9.8602142989817E+16)
[4]=>
float(9.8602142989817E+16)
[5]=>
float(9.8602142989817E+16)
[6]=>
float(9.860214298982E+16)
[7]=>
float(9.860214298982E+16)
[8]=>
float(9.8602142989822E+16)
[9]=>
float(9.8602142989822E+16)
}

PHP转换值​​因为它们都大于PHP_INT_MAX。

64位系统的结果:

int(9223372036854775807)
array(10) {
[0]=>
int(98602142989816970)
[1]=>
int(98602142989816971)
[2]=>
int(98602142989816980)
[3]=>
int(98602142989816981)
[4]=>
int(98602142989816982)
[5]=>
int(98602142989816983)
[6]=>
int(98602142989820095)
[7]=>
int(98602142989820096)
[8]=>
int(98602142989822060)
[9]=>
int(98602142989822061)
}

32位系统中的array_unique会减少数组,因为某些值​​也超过了浮子的精度。

如果没有使用SORT_NUMERIC选项,array_unique((和SORT((对于64位版本可以正常工作。

相关内容

  • 没有找到相关文章

最新更新