Число внутри
Число в mlog одно на всё — дробное двойной точности. Отсюда и предел в 53 бита, и 0.1 + 0.2 ≠ 0.3
Отдельного целого типа в mlog нет. Любое число — дробное двойной точности, то самое
double, что и в большинстве языков: 64 бита, из которых 52 отведены под мантиссу, 11 под
показатель степени и один под знак.
Из этого устройства следует всё, что дальше: и почему целые точны до определённого предела,
и почему 0.1 + 0.2 не равно 0.3, и какие биты переживут упаковку.
53 значащих бита
Заголовок раздела «53 значащих бита»Мантисса хранит 52 бита, плюс один подразумеваемый — итого 53 значащих бита. Пока число помещается в них, оно целое и точное; дальше между соседними представимыми числами появляется зазор.
| Число | Что с ним |
|---|---|
| до 2⁵³ − 1 | хранится точно, бит в бит |
| 2⁵³ = 9 007 199 254 740 992 | последнее целое, за которым начинается пропуск |
| 2⁵³ + 1 | не существует: округляется обратно к 2⁵³ |
| дальше | шаг растёт: сначала через одно, потом через два, четыре… |
В примере это видно прямо: сОдной — это 2⁵² с подмешанной единицей, и единица на месте.
А безЕдиницы — 2⁵³ с той же единицей, и её там нет: проверка равна нулю, то есть число
осталось ровно 2⁵³.
Какие биты безопасны
Заголовок раздела «Какие биты безопасны»Для битовых операций правило простое:
- биты 0–52 надёжны. Их можно ставить, читать, сдвигать — число переживёт;
- биты 53–63 существуют внутри операции, но не в переменной. Игра считает битовые операции в 64-битном целом, а результат кладёт обратно в дробное — и лишнее округляется. Теряются при этом младшие биты: старшие в числе остаются, а точность кончается снизу.
op shl метка 1 52op or упаковано упаковано меткаТак делать можно. А op shl метка 1 53 уже нет: значение в переменную вернётся, но младшие
биты рядом с ним жить не смогут.
Дроби хранятся не точнее
Заголовок раздела «Дроби хранятся не точнее»Дробное число хранится теми же 53 битами, но уже не «сколько единиц», а «сколько
двоичных долей». Десятичная 0.1 в двоичной записи бесконечна — как 1/3 в десятичной, —
поэтому хранится ближайшее представимое значение.
В примере дробь равна 0.30000000000000004, а ошибка — разница с настоящей 0.3 —
около 5.55 · 10⁻¹⁷.
Бесконечность и NaN в переменную не ложатся
Заголовок раздела «Бесконечность и NaN в переменную не ложатся»Деление на ноль даёт бесконечность, корень из отрицательного — NaN. Ни то, ни другое переменная не хранит: при записи такое значение превращается в пустоту.
op div плохо 1 0В плохо окажется null, а не «бесконечность». Поэтому проверка деления на ноль обычно
выглядит как проверка на пустоту после операции — или как проверка делителя до неё.
Неофициальный проект, с Anuke не связан. Спрайты, шрифты и переводы Mindustry © Anuke, используются по GPL-3.0; Fira Code — по OFL-1.1. Код сайта — GPL-3.0.