Степени двойки

Материал из Posmotre.li
Перейти к: навигация, поиск
Склифосовский.pngВкратце
От 0 до 255. Или от −128 до 127.
« Чем отличается начинающий программист от законченного? Начинающий думает, что в килобайте 1000 байт, законченный — что в километре 1024 метра »
— Народное творчество
« В мире есть два вида чисел: ноль, и те, которые приводят к ошибке переполнения »
— Автор неизвестен

Компьютеры работают с числами. Причем, в подавляющем большинстве случаев число разрядов в этих числах ограничено[1]. Что будет если место есть под три цифры, а нам надо записать число 9 999? Правильно, одна девятка куда-то потеряется и получится 999. Что будет если мы к этому 999 прибавим единичку? Получится 1000, но первая цифра опять куда-то потеряется и 1000 превратится в 000. Это собственно суть арифметического переполнения и есть. Для геймера это означает что невероятно раскаченный персонаж с 999 пунктами здоровья, внезапно помрет получив еще один пунктик здоровья сверху (999+1=0).

Вернемся теперь к заглавной теме. В отличие от людей, компьютер работает в двоичной системе исчисления. То есть, знает только две цифры — ноль и единицу. Попытки сделать десятичные или троичные компьютеры предпринимались, но как-то не прижилось. Поэтому, описанное в абзаце выше переполнение происходит не когда число достигает степени десятки, а когда оно достигает степени двойки. И вместо 999+1=0, выходит 255+1=0. Пока все понятно и далекому от компьютеров человеку. Однако, давайте подумаем что будет если теперь вычесть из нуля единицу? Говорите, будет −1? Нет, компьютер у нас знает ноль, знает единицу, а этот ваш минус не знает. Поэтому, мы договоримся что если первая двоичная цифра — ноль, значит число положительное (0 001=1). А если единица — отрицательное (1 001=-1)[2]. Тут жадные программисты и говорят, не хотим мы целый разряд под знак тратить, дайте нам беззнаковые числа. Окей, дают им беззнаковые числа. Но теперь при вычитании из нуля единицы, опять фигня получается — ноль превращается в 255! Ну или еще какое-то значение 2^n-1. Тут внимательный читатель может возразить что постойте, постойте, даже калькулятор в подобных ситуациях просто выдаст ошибку. Правильно, процессор тоже в таких ситуациях вывешивает флажок «ребят, тут фигня какая-то вышла». Но так уж повелось что в целях повышения быстродействия, никто на этот флажок не смотрит.

Стоит отметить что все вышесказанное актуально в основном для старых игр. Компьютеры тогда были 8-16 разрядными (с пониманием чисел больше 65535 проблемы), памяти мало (мегабайт оперативки это круто!), а у программистов было модно экономить на всем (да зачем тратить на число целых два байта? И одного хватит). Теперь компьютеры стали 64-битовыми (числа переполняются в районе 9 223 372 036 854 775 807), памяти — гигабайты, так что вышеописанные проблемы отошли в прошлое.

Примеры[править]

Как ограничение[править]

  • WarCraft II, StarCraft — ограничение на ману в 255 единиц.
    • В StarCraft обработано: энергии (космооперной маны) может быть либо 200 (без апгрейда), либо 250 (с апгрейдом и у героев), либо 180 (у брудлингов, которые теряют 1 единицу в секунду и живут 3 минуты с обоснованием, что без энергии жить не могут).
    • В эпичном редакторе карт Warcraft II на лимите в 255 завязано практически все: 25500 — максимум НР любого юнита, 2550 — максимум его цены (в каждом ресурсе), 255 — максимум его маны, защиты, базового и проникающего урона.
      • Вот только максимум разведки все-таки 9, максимум дальнобойности 15, а некоторые апгрейды стоят 3000.
  • В играх серии Heroes of Might and Magic у одного игрока не может быть больше 8 героев.
    • В четвёртой части также существует предел юнитов в 1 отряде — 32767.
  • The Elder Scrolls 4: Oblivion — ограничение на уровень характеристики или навыка в 255 единиц. Лучше всего заметно на скорости бега и высоте прыжка. Впрочем, эти значения не получить без читов.
  • В различных цветовых моделях значения каналов от 0 до 255.
  • Размеры текстур: 256×256, 512×512, 1024×1024 и т. д. Многие игры позволяют расширить текстуру вдвое или вчетверо (на этом основаны HD Pack’и старых игр). Но сделать её, например, 1000×1000 не даст уже видеоплата новые расширения команд графического процессора (уже несколько лет как) позволяют подобное сделать, однако, делать так всё же не стоит — хоть видеокарты и поддерживают текстуры, не являющиеся степенями двойки, на практике такие текстуры заметно тормозят. Потому такие картинки популярны в демках «вау! посмотри, как мы можем!», но практически не встречаются в реальных играх.
  • В Fallout 4 отсутствует ограничение на получение уровня, однако игра не может переварить значения уровня выше 65535, и вылетает.

Как ошибка[править]

  • X-COM: UFO Defense — как только сила или запас ходов солдата превысит 255, он становится немощным. В более поздних версиях на то и другое поставили предел 80.
  • Civilization — сумасшедший Ганди. Вдруг уровень агрессии скачет от нуля до 255. Это связано с тем, что при открытии демократии уровень агрессии падает на 2, однако у Индии он равен единице. А отрицательное значение игра представить не может
  • Pirates! — одна из самых первых культовых игр была, тем не менее, чрезвычайно глючной именно из-за неотслеживаемых переполнений.
  • Hearthstone — Если атака или здоровье существа превысит 65536, игрок получит существо с 1 единицей атаки/здоровья.

Примечания[править]

  1. бывает еще «w:длинная арифметика», но она тормозная. Поэтому, вы вряд ли встретите ее за пределами математических программ, которым вот кровь из носа, а нужно пересчитать все атомы во Вселенной
  2. Обычно используется более хитрый «w:дополнительный код», но суть примерно та же, так что замнем для ясности