Максимально числовое значение в bash
На курсах “Администратор ПК c Linux” на одной из лекций, посвященной языку bash, преподаватель предложил нам написать дома скрипт, который будет выводить максимальное целое числовое значение, которым может оперировать bash. Как и следовало ожидать слушатели, у которых нет технического образования с этой задачей не справились. Даже не то, чтобы не справились, а просто пытались решить ее путем прибавления единицы к числу в бесконечном цикле в надежде, что когда будет достигнуто максимальное значение, скрипт остановится, и на экране будет максимальное число, которое они выводили командой echo. Один из слушателей курса рассказал, что оставил такой скрипт работать, а когда через час подошел к компьютеру, скрипт все еще выводил значения на экран.
На самом деле все решается очень просто, если знать некоторые моменты, такие как двоичная система счисления, знаковый бит и некоторые другие. В итоге скрипт выполняется почти мгновенно и выдает точное число. Сначала приведу текст скрипта, а затем небольшие пояснения к нему.
1 2 3 4 5 6 7 8 9 10 | #!/bin/bash a=1 i=1 while [ $a -gt 0 ] do let a=a*2 let i++ done let a=a-1 echo $a |
Этот скрипт выводит максимальное число bash, которое равно - 9223372036854775807. Таким образом, можно сказать, что тип числовых данных соответствует типу bigint в других языках программирования. Напомню, что в bash переменные не имеют типа, что на самом деле не редкость. Так переменные языка PHP, изучить, который можно в школе программирования на ПХП, также не имеют типа. Но вернемся к скрипту.
Данный скрипт в цикле умножает число (начиная с единицы) на 2 и проверяет не является ли полученное число отрицательным. Чтобы понять почему вдруг положительное число должно стать отрицательным, нужно понимать, как устроена двоичная система, так как именно в ней выполняются все операции в процессоре компьютера. На определенном шаге, единица (единица - в двоичной системе), которая при каждом умножении на два - сдвигается влево на один разряд, в итоге попадает в знаковый бит регистра и число становиться отрицательным. Когда все разряды содержат нули, а знаковый содержит единицу - это максимальное отрицательное число -9223372036854775808. Чтобы из него получить максимальное положительное нужно вычесть из него единицу. Кто изучал двоичную систему тот уже понял как работает скрипт, поэтому более подробно вдаваться в подробности не буду.
Если кто-то не понял почему так и хочет разобраться - оставляйте комментарии - с удовольствием помогу.
Pe1ro:
Я понял, но не понял )
Описываемая технология ясна, не ясно с чем связано это ограничение. Ведь ясно же, что любое число (даже большее, чем 9223372036854775807) можно перевести в двоичную систему исчисления. Объясните?
Ответить
Igorka Reply:
октября 13, 2010 at 13:20
Даже не знаю как тут объяснить. Любая среда программирования (назову так условно) оперирует числами определенной разрядности. Всегда есть максимальное число (математический тип данных) с которым среда может выполнять операции. Ограничения связаны как с аппаратной частью (разрядность процессора, шины данных и прочее) так и с программной реализацией тех или иных сред программирования. Примерно так.
Ответить
riso:
Хорошее решение, но я не пойму зачем вы задали переменную i ?
Ответить
Igorka Reply:
ноября 19, 2011 at 10:14
Переменная i задавалась чтобы посмотреть количество итераций, которое показывает разрядность двоичного числа. Согласен, что здесь нужно либо вывести это число, либо убрать переменную совсем.
Ответить