Вы сможете сходу ответить на вопрос, почему в результате простейшей операции 0.1 + 0.2 в консоли браузера выведется число 0.30000000000000004?

Мы привыкли списывать такие причуды на Великие и Ужасные Особенности Языка Программирования. Ну вот работает оно так, и всё.

Согласитесь, это гораздо проще, нежели потратить десять минут на поиск информации. Но за каждым глюком скрывается фундаментальный конфликт между человеческим разумом и логикой работы конечного устройства. Мы пишем код на языках высокого уровня, оперируем привычными десятками и сотнями, а под капотами наших IDE разыгрывается нешуточная вычислительная драма.

В этой статье мы поговорим об особенностях машинной арифметики: от костылей в бортовом компьютере «Аполлона» до проблемы 2038 года. Заваривайте чаёк покрепче, и мы начинаем.

Вначале было слово

Сейчас мы воспринимаем восьмибитный байт как фундаментальную константу, нечто незыблемое и вечное, наподобие скорости света или постоянной Планка. Однако многие ранние компьютеры вообще не имели привычной нам байт-адресуемой памяти. В одних архитектурах основной единицей хранения и адресации было машинное слово, в других использовались более мелкие единицы.

В CDC 6600, например, память адресовалась 60-битными словами. Чтобы работать с отдельными символами, приходилось программно «нарезать» это гигантское слово на части (например, упаковывать по десять 6-битных символов). У советского «Минск-32» слово имело длину 37 бит (36 бит информации + 1 знаковый или контрольный разряд), а в небезызвестном PDP-8 машинное слово состояло из 12 бит.

CDC 6600, Steve Jurvetson из Menlo Park, USA. Flickr
CDC 6600, Steve Jurvetson из Menlo Park, USA. Flickr
ЭВМ «Минск-32». На Минском ордена Ленина заводе ЭВМ им. Орджоникидзе
ЭВМ «Минск-32». На Минском ордена Ленина заводе ЭВМ им. Орджоникидзе

Всё изменилось в 1964 году, когда компания IBM выпустила на рынок революционную линейку мейнфреймов System/360. Перед разработчиками встала амбициозная задача: создать универсальную машину, которая одинаково эффективно справлялась бы и с научными расчетами, и с обыкновенной бухгалтерией. Бизнесу требовалось, чтобы компьютер мог оперировать не только цифрами, но и текстом — именами клиентов, названиями товаров, адресами. А текст состоит из символов.

Ben Franske. DM IBM S360.jpg on en.wiki

В то время в IBM активно использовался старый 6-битный стандарт кодирования BCD (Binary Coded Decimal). 6 бит дают всего 64 возможные комбинации. В этот скромный лимит можно было с трудом втиснуть цифры и заглавные буквы латинского алфавита. Но для полноценного документооборота бизнесу требовались строчные буквы, знаки препинания и спецсимволы. 

Именно в System/360 байт был определен как 8 бит. Для работы с текстом использовалась 8-битная кодировка EBCDIC. Это решение оказалось чрезвычайно влиятельным и помогло закрепить восьмибитный байт в качестве стандартной единицы данных. Правда, с иероглифическими языками все равно были серьезные проблемы, японским и китайским инженерам пришлось немало поломать голову над тем, как втиснуть в компьютер все богатство родной письменности.

Термин «байт», к слову, придумал инженер IBM Вернер Бухгольц в 1956 году. Это был шутливый намек на то, что за раз компьютер может «откусить» только небольшую порцию данных (искажение от англ. bite — укус). Благодаря тотальному доминированию IBM System/360 на рынке, восьмибитный байт в считаные годы стал международным стандартом.

Но стандартизация не решила главную проблему: людям по-прежнему неудобно было общаться с компьютером на языке голых единиц и нулей. Попробуйте с ходу перевести, например, число 11010111 в десятичную систему, и вы поймете боль программистов первой волны. Инженеры начали искать удобные системы счисления, которые служили бы мостом между человеческим абстрактным мышлением и реальным компьютером.

Мы давно привыкли к стандартному квартету СС: двоичная, десятичная, шестнадцатеричная и восьмеричная (впрочем, с каждым годом она все сильнее сдает позиции). Но если копнуть поглубже, выясняется, что история высоких технологий — это целое кладбище удивительных, парадоксальных и, увы, забытых систем счисления. Вот о них мы и поговорим далее.

Аполлон-11 — когда у нуля есть знак

Бортовой компьютер «Аполлона-11», который в 1969 справился с задачей мягко посадить человека на Луну, является превосходным образчиком выворачивания классической математики наизнанку. Пока на Земле IBM продвигала свои восьмибитные байты, инженеры NASA боролись за каждый грамм веса и каждый милливатт энергии космического корабля. Их 15-битный компьютер использовал для представления отрицательных чисел обратный код. Соответственно, существовало и два нуля — «положительный ноль» (000000) и «отрицательный ноль» (111111). Сделаем ниже короткое пояснение.

Аппаратная реализация вычитания в процессорах часто сводится к сложению уменьшаемого с дополнительным кодом вычитаемого. Поэтому отдельный сложный арифметический механизм для вычитания не обязателен. В двоичной системе для этого используют три кода, где самый первый бит всегда указывает на знак: 0 для плюса и 1 для минуса. Для положительных чисел прямой, обратный и дополнительный коды абсолютно одинаковы. Например, число +5 в 4 битах всегда выглядит как 0101. Различия начинаются, когда нужно записать отрицательное число.

Прямой код числа -5 получается простой заменой знака на единицу, что дает 1101. Если инвертировать все биты этого числа, получится обратный код, то есть 1010. Главная проблема прямого и обратного кодов заключается в эффекте двойного нуля, когда в системе появляются сразу два значения: +0 как 0000 и -0 как 1000 или 1111. Из-за этого приходится тратить лишние ресурсы, чтобы проверять оба варианта нуля при вычислениях.

Эту проблему решает дополнительный код, который на данный момент является стандартом. Чтобы избавиться от лишнего минусового нуля, к обратному коду просто прибавляют 1. Для числа -5 мы берем его обратный код 1010, добавляем к нему 1 и получаем финальный дополнительный код 1011. При таком подходе значение -0 исчезает, превращаясь в обычный ноль 0000, а процессор может складывать любые числа на одной простой схеме.

Но дело происходило в 1960-е. Запросто могло получиться, что в ходе навигационных расчетов компьютер складывал два противоположных числа, и процессор выдавал -0. Как вы понимаете, логика управления двигателями должна была учитывать подобные нюансы, чтобы корабль банально не разбился на подлете к Луне. Разработчикам MIT приходилось выдумывать невероятные программные костыли, лишь бы компьютер понимал, что «отсутствие скорости» и «движение назад с нулевой скоростью» — это одно и то же с точки зрения физики. Ошибка в проверке знака у нуля могла уничтожить корабль вместе с астронавтами.

ЭВМ «Сетунь»: триты вместо битов

В 1959 году в стенах МГУ группа советских ученых под руководством Николая Брусенцова создала нечто крайне занимательное — ЭВМ «Сетунь». Эта машина работала на симметричной троичной системе счисления с базой 3. Ее минимальной единицей информации был не бит, а трит, который мог принимать три значения: -1, 0 и 1.

USSR state-owned publisher "Sputnik". https://www.alamy.com/stock-photo-scientific-staff-members-working-on-the-computing-machine-setun-22818602.html

В конце 1950-х годов советские научные институты нуждались в компьютерах, но в силу новизны и сложности технологии производство ЭВМ не поспевало за спросом. Очереди растягивались на целые годы. Поэтому академик Сергей Соболев решил, что МГУ может собрать собственную компактную, недорогую и при этом надежную машину для нужд студентов и лабораторий.

Из-за дефицита деталей в целом и низкой надежности радиоламп в частности Брусенцов принял решение обратиться к физике ферритовых сердечников и диодов. Математические расчеты показали, что троичная система счисления является наиболее плотной, экономичной и эффективной для такой элементной базы. Результат, надо сказать, превзошел все ожидания.

В 1960 году «Сетунь» была испытана и, согласно информации с официального сайта МГУ, показала «95% полезного времени, определяемого как время на решение и отладку программ, не включая время на профилактический ремонт и простои ЭВМ».

На тот момент неплохим результатом считалось даже 60% полезного времени. Соответственно, сразу после испытаний было решено запустить «Сетунь» в серийное производство.

Отрицательные числа не требовали никаких специальных знаковых битов или обратных кодов — минус был частью самой системы счисления. Более того, троичная логика идеально подходила для сложных задач моделирования, где сущностям требуется промежуточное состояние (наподобие современного null).

К сожалению, проект так и не смог набрать настоящие промышленные обороты. По воспоминаниям Николая Брусенцова, новая машина, несмотря на очевидные преимущества, была «неудобна» крупным чиновникам. За все время было выпущено только 50 ЭВМ. Сняли с производства «Сетунь» тоже несправедливо рано: спрос был отменный, готовые машины хорошо показывали себя по всей стране, от юга до крайнего севера, и хорошо переносили даже неумелое обращение персонала. К сожалению, работающего экземпляра машины не сохранилось.

Затем, как известно, наступил «тихий бум» клонирования западных технологий, преодолеть который смогли лишь единицы самобытных ЭВМ и микрокомпьютеров. А о «Сетуни» незаслуженно забыли.

Как Кармак обратный корень вычислял

Когда объемы памяти выросли, а процессоры стали 32-битными, программисты практически перестали заглядывать в бинарный код. Шестнадцатеричная система (Hex) окончательно утвердилась как стандарт де-факто, поскольку оказалась тем самым идеальным интерфейсом между человеком и машиной: один байт элегантно упаковывался всего в два символа от 00 до FF, а длинные адреса превращались в компактные конструкции вроде 0x7FFF.

Так как один Hex-символ всегда равен ровно четырем битам, программист своими глазами видит границы байтов. Например, если вам нужно включить самый первый (знаковый) бит в 32-битной структуре, в Hex пишется 0x80000000. В десятичной системе это превратится в 2147483648 — абсолютно нечитаемое число, в котором битовая логика полностью скрыта. Надо сказать, в умелых руках Hex как инструмент действительно творил чудеса.

В 1999 году мир увидел культовый шутер Quake III Arena. Игра на тот момент поражала плавностью работы вкупе с отличной 3D-графикой. При этом даже на слабой машине можно было успешно поиграть на высокой частоте кадров. Секрет крылся в гениальном алгоритме быстрого вычисления обратного квадратного корня. Эта математическая операция необходима для расчета трехмерного освещения, отражений и физики частиц. Для корректной работы игры требовалось выполнять ее по несколько тысяч раз за фрейм. При этом классический подход с делением не давал нужной производительности и намертво «вешал» игру.

Представьте себе: процессор сначала должен взять число, найти его корень, а затем разделить единицу на этот корень. Операция деления чисел типа float на архитектурах тех лет была невероятно «дорогой» и занимала десятки тактов процессора: непозволительная роскошь для сложной трехмерной игры, целевая аудитория которой вряд ли располагала суперсовременным «железом».

Джон Кармак воспринял это как личный вызов. Он элегантно обошел это ограничение, провернув безумный трюк на стыке шестнадцатеричной системы счисления и стандарта хранения чисел с плавающей точкой (IEEE 754). В результате трюка дорогостоящую операцию удалось заменить несколькими дешёвыми целочисленными операциями и одним шагом метода Ньютона. На тогдашнем железе такой подход мог быть значительно быстрее стандартного вычисления через FPU. Код выглядел так:

float Q_rsqrt( float number ) {

long i;

float x2, y;

const float threehalfs = 1.5F;

x2 = number * 0.5F;

y = number;

i = ( long ) &y;

i = 0x5f3759df - ( i >> 1 );

y = ( float ) &i;

y = y ( threehalfs - ( x2 y * y ) );

return y;

}

Обратите внимание на строчку i = 0x5f3759df - ( i >> 1 );. Программа брала число типа float, временно интерпретировала его биты как обычное целое число, сдвигала всю эту бинарную цепочку на один бит вправо (i >> 1) и вычитала результат из Hex-значения. 

Никто долго не мог понять математическую природу этого числа. За счет побитового сдвига и особенностей представления float алгоритм получал очень хорошее начальное приближение обратного квадратного корня, после чего уточнял его методом Ньютона. Эта строчка кода до сих пор считается одной из самых ярких вспышек инженерного гения в истории разработки.

Впрочем, не будем лукавить. В 2005 году, когда исходники Quake III были опубликованы, Кармак признался, что взял этот код из чьих-то старых наработок. Поэтому воздадим ему должное: на его месте далеко не всякому программисту хватило бы терпения и эрудиции найти подходящее решение и умело его интегрировать в свой код.

По итогам журналистского расследования, стартовавшего вслед за публикацией исходного кода, выяснилось, что корни «магического числа» 0x5f3759df уходят в 1980-е. Главным «подозреваемым» считается Грег Уолш, один из основателей Ardent Computer. Он разработал сам принцип побитового сдвига для вычисления корня, а дорабатывали и вычисляли точное значение константы математики Клив Моулер (создатель MATLAB) и Гэри Таролли (основатель легендарной компании 3dfx, создававшей видеокарты Voodoo). Кармак же просто наткнулся на этот трюк, изучая открытые кодовые базы, и применил его очень к месту. 

После одного шага метода Ньютона ошибка для классической реализации снижалась примерно до 0,17%, чего для расчета освещения в игре было вполне достаточно.

Linux и восьмеричная система счисления

Пока шестнадцатеричная система счисления набирала обороты, ее предшественница, восьмеричная система (Octal), медленно отмирала. Она была популярна во времена 12- и 36-битных компьютеров, потому что позволяла разбить машинное слово на аккуратные триплеты битов (2³ = 8). С появлением восьмибитного байта нужда в Octal практически отпала. Но не везде.

Каждый системный администратор и DevOps-инженер сталкивается с восьмеричной системой на регулярной основе. С ее помощью задаются права доступа в операционных системах семейства Unix и Linux.

Когда вы пишете в терминале команду chmod 755, вы используете Octal. Дело в том, что права доступа к файлам в Linux состоят из трех групп (владелец, группа, остальные), и внутри каждой группы есть ровно три флага: чтение (r), запись (w) и исполнение (x).Каждая группа — это идеальный трехбитный триплет.

Например, 111 в двоичной системе — это 7 в восьмеричной (полные права: rwx). 101 в двоичной системе — это 5 в восьмеричной (чтение и исполнение: r-x). Если бы создатели Unix использовали шестнадцатеричную систему, кодировать права было бы неудобно: оставались бы «лишние» биты, которые ломали бы всю красоту подхода. Восьмеричная система счисления идеально легла на эту концепцию – и поэтому еще долгое время останется актуальна, пусть даже в таком рудиментарном виде.

Unix Epochalypse

Все эти исторические курьезы и хаки из девяностых могут показаться делами давно минувших дней. Теперь у нас есть терабайты памяти, мощные IDE и 64-битные процессоры, так что подобные проблемы, казалось бы, должны остаться в прошлом. Но прямо сейчас в самом сердце миллиардов цифровых устройств тикает часовая бомба, заложенная еще создателями операционной системы Unix. Называется она проблемой 2038 года (или Y2K38).

Как современный компьютер определяет сегодняшнее число и время суток? В Unix-подобных системах (включая Linux, macOS, Android и прошивки роутеров и прочих умных чайников) время отсчитывается в секундах, прошедших с полуночи 1 января 1970 года. Эта концепция называется Unix Epoch (Эпоха Unix). Проблема возникает в старых системах и legacy-коде, где time_t реализован как 32-битное знаковое целое число. Один бит используется под знак, поэтому для счетчика секунд остаётся 31 бит. Максимальное значение — 2³¹ - 1, или 2 147 483 647 секунд.

А теперь переведем эти секунды в понятные нам даты. Счетчик заполнится 19 января 2038 года в 03:14:07 по всемирному времени (UTC). В эту секунду 32-битный регистр времени будет выглядеть в двоичном коде как 01111111 11111111 11111111 11111111.

Что произойдет ровно через одну секунду, в 03:14:08? Переполнение. Вся цепочка единиц превратится в нули, а в самый левый знаковый бит перенесется единица. Компьютер увидит строку 10000000 00000000 00000000 00000000. Эта комбинация означает минимально возможное отрицательное число: -2 147 483 648. Для операционной системы время мгновенно открутится назад на 68 лет от начала Unix Epoch, в 13 декабря 1901 года. 

В зависимости от конкретной системы последствия могут быть очень разными — от некорректных дат и логов до ошибок в базах данных, планировщиках, протоколах и программном обеспечении, которое работает с сертификатами и сроками действия.

И если современные десктопы и смартфоны уже давно перешли на 64-битные процессоры и типы данных (где лимита времени хватит еще на 292 миллиарда лет), то в мире интернета вещей (IoT), встроенных систем и старого софта эта проблема стоит невероятно остро.

Разумеется, решения уже есть, и они планомерно внедряются. На современных 64-битных Linux-системах классическая проблема переполнения 32-битного time_t уже не актуальна — время представляется 64-битными значениями. А вот старые 32-битные системы и embedded-устройства по-прежнему требуют отдельной проверки.

Для устройств, физически неспособных обрабатывать 64-битные числа, было решено убрать бит знака и тем самым отвести под хранение времени все доступные 32 бита. Компьютер полностью теряет способность понимать даты до 1970 года (они превращаются в огромные числа из будущего), но для условных датчика температуры в прихожей или умной плиты это совершенно не критично. В этом случае «большой барабум» переносится на 7 февраля 2106 года.

Последний вариант – Time Windowing. Если перепрошить устройство не получится, можно создать над ним слой абстракции. Пускай древняя БД «думает», что на дворе 1996 год – мы-то знаем, что отмотали ей время ровно на 30 лет назад, и будем учитывать сдвиг, получая из нее даты. Этот метод применяется в старых закрытых коммерческих программах, исходный код которых утерян, а сами они зашиты в ПЗУ станков или банковских терминалов.

Так что запасаться попкорном и ждать очередного апокалипсиса в духе 2000 года не стоит. Просто не говорите своей старой-доброй микроволновке, что будущее уже наступило.

Вся история программирования — это хроника компромиссов. Мы берем бесконечно огромный, плавный и живой аналоговый мир, пропускаем его через мясорубку дискретных систем счисления, а после героически пишем костыли, чтобы сгладить углы, допущения, шероховатости и неточности.

Мы молодцы. Мы научили компьютер понимать буквы. Заставили шестнадцатеричные константы участвовать в просчете физики света в 3D-играх. Даже права доступа красиво упаковали в восьмеричную СС. Однако мыслить по-человечески компьютер от этого не стал.

Совсем скоро этот зоопарк тоже станет частью истории. Эра квантовых вычислений готовит революцию, которая вообще уничтожит привычное понятие систем счисления. Квантовый кубит работает по совершенно иным законам. Но пока этого не произошло, следует помнить: за каждым элегантным интерфейсом на реакте или строчкой кода на питоне всегда стоят регистры памяти. И побеждает тот программист, который умеет думать не только абстракциями высокого уровня, но и понимает, как его код выглядит там, в самом низу, в виде череды единиц и нулей.

P.S.

В JavaScript (и многих других языках программирования) выражение 0.1 + 0.2 возвращает 0.30000000000000004 из-за особенностей двоичного представления чисел с плавающей точкой. Компьютеры не могут с совершенной точностью записать некоторые десятичные дроби в двоичной системе.

JavaScript использует стандарт IEEE 754. На каждое число выделяется ровно 64 бита памяти. Бесконечная дробь обрезается и округляется. При сложении двух уже округленных чисел погрешности суммируются, и на конце появляется лишняя четверка.

Комментарии (10)


  1. Arhammon
    18.08.2026 03:07

    Мы давно привыкли к стандартному квартету СС: двоичная, десятичная, шестнадцатеричная и восьмеричная (впрочем, с каждым годом она все сильнее сдает позиции).

    В углу, поглядывая на часы и чертежи, плачет 60-ричная система 5000+ летней давности...


  1. LavaLava
    18.08.2026 03:07

    Кармак признался, что взял этот код из чьих-то старых наработок

    Вот так рептилоиды и легитимизмруют передачу знаний и технологий человекам)


  1. sergyk2
    18.08.2026 03:07

    встроенных систем и старого софта эта проблема стоит невероятно остро.

    никто не думает что будет через 10 лет, да и эти ваши умные чайники к тому ремени устареют и "сломаются".


    1. CrashLogger
      18.08.2026 03:07

      Чайники то ладно, а вот бортовые компьютеры самолетов и системы управления ядерных реакторов могут преподнести сюрприз) Такие системы работают десятилетиями и обновить их не всегда возможно.


      1. sergyk2
        18.08.2026 03:07

        промышленные системы разрабатываются по другим стандартам, да и заменить бортовой компьютер в рамках регламентных работ не представляет сложность


  1. andy_p
    18.08.2026 03:07

    старый 6-битный стандарт кодирования BCD (Binary Coded Decimal)

    BCD - это не 6-ти битный код. Это когда два десятичных разряда в один байт упаковывают.


    1. CrashLogger
      18.08.2026 03:07

      Это другое BCD)


  1. SIISII
    18.08.2026 03:07

    Однако многие ранние компьютеры вообще не имели привычной нам байт-адресуемой памяти

    Не многие, а вообще все действительно ранние. Деление машинного слова на 8-битные байты, а заодно чёткое и официальное отделение архитектуры (грубо говоря, системы команд) от реализации (физическое воплощение), что открыло дорогу программной совместимости "снизу вверх", изобрела IBM в Системе 360 (1964 год), о чём ниже пишет автор, но и после неё появлялись машины без такого деления (например, знаменитая линейка мини-ЭВМ HP 2100, 1967 г., с 16-битным словом, но на байты не делившемся и из-за этого весьма неудобная для, например, обработки символьной информации).

    В то время в IBM активно использовался старый 6-битный стандарт кодирования BCD (Binary Coded Decimal). 6 бит дают всего 64 возможные комбинации

    Строго говоря, как указано в одном из комментариев выше, BCD -- это чисто кодирование десятичных цифр 0-9 четырьмя битами с комбинациями 0000-1001; остальные комбинации использовались для представления знака. Но 6-битные символьные кодировки действительно были и использовались.

    Благодаря тотальному доминированию IBM System/360 на рынке, восьмибитный байт в считаные годы стал международным стандартом

    Не было никакого тотального доминирования. Например, небезызвестный Дейкстра поливал и IBM, и Систему 360 грязью и вовсю расхваливан мэйнфреймы Burroughs, в которой работал -- и которые были нагромождением целой кучи нелепиц, выглядевших теоретически красиво, но на практике создававших лишь кучу проблем (виртуальная память на основе сегментов переменной длины, безадресная стековая система команд, определение типа информации в машинном слове с помощью обязательного поля тэга -- и никаких тебе байтов). В итоге и машины Burroughs, и все другие архитектуры мэйнфреймов проиграли конкуренцию и сошли со сцены, а сами компании зачастую исчезли или сменили профиль деятельнсти -- но это было уже в 1980-х.

    Байты же стали доминировать благодаря их удобству: 256 символов было достаточно для представления основных алфавитов (да, иероглифические оставались за бортом, но тогда думали о нуждах, в первую очередь, США, во вторую -- Европы, а Японию, и тем более Китай с Кореей никто в расчёт не брал), а заодно в одном байте можно было хранить две десятичные цифры в BCD и оперировать прямо ими, что очень важно для экономических расчётов.

    Аполлон-11 — когда у нуля есть знак

    Весь раздел вызывает определённые сомнения, особенно в плане знака.

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

    Однако научные расчёты обычно требуют операций с плавающей запятой -- а там для представления значащей части (мантиссы) по-прежнему используется прямой код, поэтому у любого современного компьютера будет два вещественных нуля и две бесконечности -- положительная и отрицательная. Соответственно, задача тем или иным образом это учитывать не является уникальной для Аполлона, она вполне актуальна и сегодня, но обычно не требует дополнительных усилий (сравнение вещественного нуля с нулём даст "истину" независимо от знаков этих нулей).

    Затем, как известно, наступил «тихий бум» клонирования западных технологий, преодолеть который смогли лишь единицы самобытных ЭВМ и микрокомпьютеров. А о «Сетуни» незаслуженно забыли.

    Ну, о старом вообще постоянно забывают, а помнят лишь увлечённые темой люди или профессионалы в соответствующей теме.

    Троичная система имела определённые преимущества, но недостатков для чисто электронной реализации у неё куда больше -- поэтому она и не "взлетела" (два состояния "транзистор открыт/транзистор закрыт" отслеживать куда проще и надёжнее, чем три состояния).

    Что же касается "самобытных ЭВМ", то СССР уже в 1960-е прилично отставал от Запада, а с системным ПО был вообще полный швах: нормой у нас было программирование не на ассемблере даже, а прямо в машинных кодах. Собственно, именно желание получить кучу готового системного ПО и трансляторов в итоге и привело к решению копировать архитектуру Системы 360; своё системное ПО для отечественных машин -- тех же БЭСМ-6 и "минсков" -- стало по-настоящему появляться лишь в 1970-е и под влиянием западного ПО.

    Сами же наши ЭВМ 1960-х годов в общем и целом были вполне на уровне, но ничего шедеврального из себя с инжерерной точки зрения не представляли -- вполне обычные машины в своих классах.

    Дальнейшее нарастание проблем связано не с этим, а с тем, что от копирования архитектуры (т.е. системы команд, грубо говоря, что и требовалось для обеспечения совместимости и возможности использовать готовое ПО) перешли к копированию всего подряд на физическом уровне вместо разработки своего "по образу и подобию". Скажем, были полностью свои микропроцессоры с системой команд PDP-11/LSI-11 (серия 1801), но зачем-то скопировали и DECовские микросхемы (например, серия 1811, хотя их полно было). Соответственно, кучу ресурсов тратили на, по сути, перерисовывание кристаллов, хотя сложные вещи типа процессоров куда проще сделать с нуля самим -- что и делали успешно, когда такая возможность была.

    Ну а если "зреть в корень", то проблема была в советской социалистической экономике с абсолютной государственной монополией на всё. На Западе любая фирма могла что-то попытаться сделать на свой страх и риск и на свои деньги -- а дальше уже "рыночек решал". У нас всё упиралось в госфинансирование, т.е. за "близость к телу"; на энтузиазме и скромных ресурсах, имеющихся под рукой, можно было сделать лишь мелочь вроде той же "Сетуни" -- и то под крылом госконторы и с одобрения его руководства.

    Операция деления чисел типа float на архитектурах тех лет была невероятно «дорогой» и занимала десятки тактов процессора

    Она и сейчас дорогая, если сравнивать с другими операциями. Да, за счёт 100500 млрд. транзисторов процесс можно несколько ускорить, но деление всё равно остаётся самой медленной операцией.

    В 2005 году, когда исходники Quake III были опубликованы, Кармак признался, что взял этот код из чьих-то старых наработок.

    Я лично встречал быстрое приближённое вычисление корня на 8-разрядном микропроцессоре 8080 году эдак в 1992 или 1993-м; числа с плавающей запятой там сделали трёхбайтовыми, исходя из требуемой для задачи точности. Правда, что за алгоритм это был, я понятия не имею.

    Дело в том, что права доступа к файлам в Linux состоят из трех групп (владелец, группа, остальные), и внутри каждой группы есть ровно три флага: чтение (r), запись (w) и исполнение (x).Каждая группа — это идеальный трехбитный триплет.

    На самом деле, не это было первопричиной.

    UNIX, как мы его привыкли знать, появился на 16-разрядной PDP-11 (более ранние версии на, кажется, 18-разрядной PDP-7 ещё не были "этим" Унихом, сначала была вообще однозадачная примитивнейшая UNICS). У архитектуры PDP-11 имеется восемь регистров и восемь видов адресации, поэтому коды команд очень удобно записывать именно в восьмеричной системе счисления. Например, команда ADD R3,@R4 имеет машинный код 060314 (четыре старших бита -- 06 -- задают сложение; 03 -- регистровая адресация с регистром 3, 14 -- косвенная регистровая адресация с регистром 4).

    Соответственно, в мире PDP-11 восьмеричная система применялась везде, и даже там, где это, в общем-то, не требовалось. Например, в самой развитой из операционных систем DEC, RSX-11, внешние устройства задавались двумя буквами с последующим номером в восьмеричной, а не десятичной системе, например, TT10: обозначает терминал № 8, а ему предшествует TT7:.

    Так что использовать восьмеричную систему и для маски прав доступа или ещё чего подобного было для привыкших к PDP-11 обычным делом. Лично я не исключаю даже, что сам набор прав искусственно подогнали к трём битам, чтобы записывать было удобно.

    Unix Epochalypse

    Подобное вообще регулярно случается. Можно, например, вспомнить про "проблему 2000-го года". Где-то была информация, что из-за использования 32-битного счётчика миллисекунд в каком-то авиационном ПО пришлось выпустить специальное предписание полностью обесточивать бортовую аппаратуру самолётов на стоянках, чтобы при каждом вылете счётчик начинал работу с нуля -- иначе за месяц с небольшим возникало переполнение и связанные с этим проблемы (а современная бортовая электроника жрёт настолько мало, что на стоянке её могли и не отключать -- аккумуляторов ей на месяцы хватит, а не на полдня до следующего вылета).

    Аналогичная проблема была и с часами IBMовских мэйнфреймов, введёнными в Системе 370 (в Системе 360 был лишь примитивный таймер, кидающийся прерываниями): они 64-битные, но миллисекунды прибавляются, если память не изменяет, к 51-му биту (старшим битом является нулевой -- на этих машинах биты нумеруются слева направо, а не более привычным способом справа налево), поэтому полный цикл часов -- опять-таки, если память не подводит -- равен 144 годам, при этом за точку отсчёта было принято начало 1900-го года. Но в z/Architecture этой проблемой озаботились заранее и к 64-разрядным часам добавили т.н. индекс эпохи: сначала он равен 0, затем 1 и так далее. Так что техническую базу для преодоления проблемы там создали, необходимые изменения в ОС наверняка давно уже внесли. А вот с прикладным ПО могут, в принципе, возникнуть проблемы -- это уж от разработчиков зависит, а также способа использования.

    JavaScript использует стандарт IEEE 754. На каждое число выделяется ровно 64 бита памяти.

    Вообще, стандарт IEEE 754 не требует, чтоб число было непременно 64-битным; более того, 32-битные вещественные числа куда более распространены. Хотя конкретно JavaScript, вполне может быть, использует именно 64-битные числа двойной точности.

    При сложении двух уже округленных чисел погрешности суммируются, и на конце появляется лишняя четверка

    Во многих случаях дело не в "сложении погрешностей", а в принципиальной невозможности точно представить значение конкретного числа в ограниченном числе разрядов. Десятичную дробь 1/3 в десятичной системе записать точно тоже невозможно: будет 0,3333.... с бесконечными тройками (математик напишет на бумаге 0,(3), но в вычислительной технике такой трюк невозможен). А вот в троичной системе это число было бы записано точно, но многие точные десятичные стали бы неточными, и т.д.


    1. domix32
      18.08.2026 03:07

      Троичная система имела определённые преимущества, но недостатков для чисто электронной реализации у неё куда больше -- поэтому она и не "взлетела" (два состояния "транзистор открыт/транзистор закрыт" отслеживать куда проще и надёжнее, чем три состояния).

      был несколько разочарован узнать, что физически троичные гейты сетуни были на самом сдвоенной двубитной парой и лишнее значение использовалось как trap или прерывание. Ещё иишница убеждала меня, что ферритовые стержни были относительно дорогим развлечением по простой причине отсутвия их массового производства, что также сыграло роль в вымирании устройства.


    1. piton_nsk
      18.08.2026 03:07

      Комментарий содержательнее статьи