Это вопрос исследования, то есть я не совсем уверен, о чем этот вопрос, но я думаю, что это самое большое целое число в Bash. Во всяком случае, я буду определять это реже.
$ echo $((1<<8))
256
Я делаю целое число, немного сдвигая. Как далеко я могу пойти?
$ echo $((1<<80000))
1
Не так далеко, по-видимому. (1 неожиданно, и я вернусь к нему.) Но,
$ echo $((1<<1022))
4611686018427387904
все еще положительный. Не это, однако:
$ echo $((1<<1023))
-9223372036854775808
И на шаг дальше,
$ echo $((1<<1024))
1
Почему 1? И почему следующее?
$ echo $((1<<1025))
2
$ echo $((1<<1026))
4
Кто-то хотел бы проанализировать эту серию?
ОБНОВИТЬ
Моя машина:
$ uname -a
Linux tomas-Latitude-E4200 4.4.0-47-generic #68-Ubuntu SMP Wed Oct 26 19:39:52 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
bash
arithmetic
Жиль "ТАК - прекрати быть злым"
источник
источник
Ответы:
Bash использует
intmax_t
переменные для арифметики . В вашей системе они имеют длину 64 бита, поэтому:который
в двоичном формате (1 с последующим 62 0). Сдвиньте это снова:
который
в двоичном (63 0 с), в арифметике дополнения до двух.
Чтобы получить наибольшее представимое целое число, вам необходимо вычесть 1:
который
в двоичном
Как было отмечено в ilkkachu «s ответ , сдвигая берет смещение по модулю 64 на 64-разрядных x86 процессоров (независимо от использования
RCL
илиSHL
), который объясняет поведение , которое вы видите:эквивалентно
$((1<<0))
. Таким образом ,$((1<<1025))
это$((1<<1))
,$((1<<1026))
это$((1<<2))
...Вы найдете определения типов и максимальные значения в
stdint.h
; в вашей системе:источник
-
имеет более высокий приоритет, чем<<
.echo $((1<<63-1))
дает мне4611686018427387904
.$((1<<63-1))
равно$(((1<<63)-1))
.Из
CHANGES
файла дляbash
2.05b:На машинах x86_64
intmax_t
соответствует 64-разрядным целым числам со знаком. Таким образом, вы получаете значимые значения между-2^63
и2^63-1
. За пределами этого диапазона вы просто получаете обходы.источник
-2^63
и2^63-1
включительно.Сдвиг на 1024 дает единицу, потому что величина сдвига эффективно берется по модулю количества бит (64), а значит
1024 === 64 === 0
, и1025 === 65 === 1
.Сдвиг чего-то другого, кроме a,
1
дает понять, что это не битовое вращение, поскольку старшие биты не переходят в нижний предел, пока значение сдвига не станет (как минимум) 64:Может случиться так, что это поведение зависит от системы. Код bash, на который ссылается Стивен, показывает просто сдвиг, без какой-либо проверки правого значения. Если я правильно помню, процессоры x86 используют только младшие шесть битов значения сдвига (в 64-битном режиме), поэтому поведение может быть напрямую из машинного языка. Кроме того, я думаю, что сдвиги более чем на битовую ширину также не определены четко в C (
gcc
предупреждает об этом).источник
Пока целочисленное представление не оборачивается (по умолчанию в большинстве оболочек).
64-битное целое число обычно переносится в
2**63 - 1
.Это
0x7fffffffffffffff
или9223372036854775807
в дек.Это число «+1» становится отрицательным.
Это так же, как
1<<63
, таким образом:После этого процесс повторяется снова.
Результат зависит
mod 64
от значения сдвига [a] .[a] От: Руководство разработчика программного обеспечения для архитектуры Intel® 64 и IA-32: Том 2 Счетчик маскируется до 5 бит (или 6 бит, если в 64-битном режиме используется REX.W). Диапазон счета ограничен от 0 до 31 (или 63, если используется 64-битный режим и REX.W). ,
Также: помните, что
$((1<<0))
это1
Итак, все зависит от того, насколько близко число к кратному 64.
Тестирование лимита:
Надежный способ проверить, какое максимальное положительное (и отрицательное) целое число - это проверить каждый бит по очереди. В любом случае, для большинства компьютеров он менее 64 шагов, и он не будет слишком медленным.
удар
Сначала нам нужно самое большое целое число в форме
2^n
(1 бит, за которым следуют нули). Мы можем сделать это, сдвигая влево, пока следующий сдвиг не сделает число отрицательным, также называемое «обтекание»:где
b
результат: значение перед последним сдвигом, который не проходит цикл.Затем нам нужно попробовать каждый бит, чтобы выяснить, какие из них влияют на признак
e
:Максимальное целое число (
intmax
) является результатом последнего значенияd
.На отрицательной стороне (меньше чем
0
) мы повторяем все тесты, но тестируем, когда бит можно сделать равным 0, не оборачиваясь.Целый тест с печатью всех шагов таков (для bash):
ш
Переводится практически на любую оболочку:
При выполнении вышеуказанного для многих оболочек
все (кроме bash 2.04 и mksh) принимали значения до (
2**63 -1
) на этом компьютере.Интересно сообщить, что оболочка att :
вывел ошибку на значениях
$((2^63))
, а не ksh.источник