Если я сделаю это в PHP:
echo (int)9223372036854775808;
Выходное значение равно -9223372036854775808, что делает его идеальным, поскольку с 9223372036854775807 в двоичном виде:
0111 ... 1
то есть 0, а затем 63. И, очевидно, 1 в двоичном виде это всего лишь 1, поэтому, когда я добавляю их, я получаю 1000 … 0 (1 с 63 0s после него), что составляет -9223372036854775808 в 2-й записи дополнения.
Поэтому я ожидаю, что если я сделаю что-то вроде добавления -1 к -9223372036854775808, я получу обратно 9223372036854775807. Аналогия в 4-битном двоичном коде будет выглядеть так:
1000 (-8)
1111 (-1)
----
0111 (7)
Я понимаю, что не могу просто присвоить -9223372036854775809 переменной, потому что ее нет в 64-битных целых числах со знаком, но почему это не работает:
$smallest_int = (int)-9223372036854775808;
echo (int)($smallest_int-1); //similar to 1000+1111 in 4 bit
Когда я запускаю это, выход все еще -9223372036854775808. Почему это происходит? Это как-то связано со слабой типизацией PHP? Это происходит на других языках (я знаю, что это точно не происходит в C)?
Это правда, что 9223372036854775808 становится -9223372036854775808, но это не так просто, как просто «обтекание целых чисел». Вот еще несколько сопоставлений (найденных экспериментально):
Так что вы можете подумать, что цифры за пределами int
диапазон все отображается на -9223372036854775808 — но подождите! :
Все это кажется мне совершенно произвольным. Я думаю, что происходит то, что значения длиной более 18 цифр (и, следовательно, легко распознаваемые как находящиеся вне целочисленного диапазона) по существу отбрасываются и заменяются нулями, тогда как значения длиной 18 цифр анализируются только в том случае, если они находятся в диапазоне, но используя логику, которая не предназначена и не предназначена для согласования значений, выходящих за пределы допустимого диапазона.
Я предполагаю, что поскольку число не набрано, PHP фактически конвертирует ваше число в плавающее, а затем в математических вычислениях теряется -1.