Ключи массива PHP изменяются на отрицательное значение между определенным диапазоном чисел

По стечению обстоятельств я столкнулся с очень странным поведением в отношении массивов PHP и его ключей. Рассмотрим это создание массива PHP.

$arr[2250572483]=1;
//dump the array
var_dump($arr);
//Result:
array(1) { [-2044394813]=> int(1) }

Каким-то образом ключ массива изменил свое значение на совершенно другое отрицательное число. Это привело меня к дальнейшему исследованию, которое до сих пор не дало результатов.
В приведенном ниже примере я зацикливаюсь между диапазоном чисел 2250572300 и 2250572500. У меня мало времени, поэтому мне не удалось точно определить, с какого числа это явление начинает происходить, потому что я запускаю из памяти перебирает большой диапазон чисел. Я думаю, что это должно быть где-то между 2100000000 и 4300000000.

$arr2 = array();
for($i=2250572300; $i<= 2250572500; $i++){
  $arr2[$i]=$i;
}
echo "<pre>".var_export($arr2,true)."</pre>";

Мой вопрос: кто-нибудь знает, как и почему это происходит, и есть ли что-нибудь, что в настоящее время делается для решения этой проблемы?

По сути, это серьезный недостаток PHP, который потенциально может сделать PHP бесполезным, когда вы работаете с числами в массивах, например, с поставщиком, счетом-фактурой, номером товара и т. д.

Спасибо


person tuberider    schedule 22.05.2014    source источник
comment
У меня работает: 3v4l.org/6nD3C и второй пример тоже: 3v4l.org/Feooi   -  person WizKid    schedule 22.05.2014


Ответы (2)


Вы используете целочисленное значение в качестве ключа массива. Все целые числа в PHP являются целыми числами со знаком, а в 32-разрядных системах максимальное значение равно 232 - 1 (задается PHP_INT_MAX). Если целочисленное значение больше PHP_INT_MAX, оно переносится и дает в результате $key % PHP_INT_MAX.

Подтвердить:

echo 2250572483 % PHP_INT_MAX; // => -2044394813

Решением будет использование ключа в виде строки, то есть $arr['2250572483']=1;. Однако это не должно быть проблемой в 64-разрядных системах (где верхний предел равен 264 - 1).

person Amal Murali    schedule 22.05.2014
comment
Привет, Амаль. Простое заключение числа в кавычки не делает его строкой в ​​PHP, поэтому работает 3 * 4 = 12. $arr['2250572483']=1 все еще имеет проблему. Выполнение таких действий, как $arr[(string)2250572483] не работает. Я понимаю, что проблема в 32-битной компьютерной системе, но я все равно могу явно указать 2250572483 как строковое значение. PHP рассматривает его как число, даже если оно заключено в кавычки. Вы можете сделать что-то вроде $arr[2250572483 ]=1, а затем обрезать его, но почему я должен делать такие обходные пути. Проблема в том, что PHP интерпретирует строку как число, если все символы являются числами. - person tuberider; 23.05.2014

Это как-то связано с тем, как сохраняются целые числа. Первый бит (слева) говорит, если вы положительны + или отрицательны - и с этим поведением результат с большими целыми числами будет таким, как вы его описали. Что у вас есть отрицательное целое число.

person Baalthasarr    schedule 22.05.2014