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

Вы когда-нибудь пробовали узнать о числах с плавающей запятой и бросали, натолкнувшись на такие термины, как «мантисса», «экспонента», «FPU», «IEEE 754» - или, что еще хуже, видели ужасное «уравнение для чисел с плавающей запятой»?

Давайте отбросим все эти термины. Давайте просто поговорим о числах с плавающей запятой, не предполагая знания двоичных чисел, байтов или оснований.

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

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

С первого взгляда 👓

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

Скромная метрическая палка 📏

Измерительная линейка (или измерительная линейка) - это мерная линейка длиной ровно 1 метр. Обычно он будет иметь толстые отметки через каждые 10 см, чуть более тонкие отметки через каждые 1 см и более тонкие отметки через каждые 1 мм.

Обратите внимание, что:

  • 1 м в 10 раз больше 10 см
  • 10 см в 10 раз больше 1 см
  • 1 см в 10 раз больше 1 мм

Это стоит того, чтобы позвонить. Эта измерительная линейка имеет точность 1 мм, а отметки установлены в базе 10.

Точность vs точность 🏎️

Давайте определим здесь два термина. Точность - насколько результат близок к его «реальной ценности». Точность - это то, насколько точен ваш результат. В качестве глупого примера предположим, что мы должны были измерить длину автомобиля, которая на самом деле была 254 сантиметра в длину, но в километрах.

Сказать, что это 132,327521 километра, было бы очень точно, но и очень неточно.

Сказать, что это 0 километров, было бы очень неточно, но на самом деле было бы намного точнее, чем первое значение.

Точный И точный ответ будет 0,00254 километра.

Мы также будем использовать термин наименьшее представимое значение для обозначения точности.

Измерительные палочки ‘R Us Ltd.

Представим себе компанию (сокращенно MeSticks), которая решила заработать состояние на производстве и продаже мерных палочек. Было создано два основных продукта: Fixed Stick и Floating Stick.

При разработке этих палочек наша компания имеет достаточно древесины, чтобы сделать палочек сколь угодно широкой! Однако в наши дни дорогие чернила для принтеров ограничены тем, сколько отметок они могут напечатать на каждой палочке. И они не хотят идти на компромисс в отношении качества чернил - на их качественных линейках можно наносить только самые темные и гладкие черные чернила.

Фиксированные палки 🔨

Представим, что они хотят построить палку длиной 1 метр. Из-за ограничений чернил они могут нанести на линейку ровно 1000 знаков (не считая написанных цифр). Итак, если мы разделим 1 м на 1000, мы получим 1 мм. Они могут поставить отметку через каждые 1 мм.

Мы скажем, что наибольшее представимое значение ручки составляет 1 метр. Наименьшее представимое значение - 1 мм.

Если мы хотим отмерить 36,7 см на этой палке, для нас это не проблема. Мы видим, что это 367 мм.

Но что, если мы хотим измерить что-то большее, скажем, 242 см? Наша палка для этого слишком мала. Так что давайте выбросим его и возьмем тот, который увеличен в 10 раз!

Большая фиксированная палка

Эта новая палка имеет длину 10 метров. Количество отметок, которые мы можем сделать на палочке, останется прежним - 1000, поэтому теперь мы будем видеть отметку через каждые 1 м, каждые 10 см и 1 см. Но мы не сможем правильно отмерить 1 мм. Теперь точность составляет 1 см. Наибольшее представимое значение - 10 м, наименьшее представимое значение - 1 см. Поскольку мы увеличили его и получили точность меньше (или равную) 1 см, мы с радостью можем измерить 242 см без проблем!

Но мы больше не можем измерять 36,7 см, как раньше. Мы потеряли точность и можем измерить только 36 или 37 см - в этом случае мы, вероятно, округлим до 37. Однако мы должны принять решение, и это ключевой момент.

Если бы мы хотели, мы могли бы попросить MeSticks сделать еще одну палку, которая в 10 раз больше, чтобы измерить еще большее значение, например 770 см (но не 767 см).

Или мы могли бы получить тот, который в 10 раз меньше, чем наш первый, и измерить что-то намного меньшее, например, 9,4 мм. Но если мы используем меньший, мы ограничиваем максимальный размер, который можем измерить.

Независимо от размера палки, MeSticks всегда допускает на ней ровно 1000 отметок - ни больше, ни меньше.

Если вы следовали этому разделу, теперь вы должны понять основную концепцию чисел с фиксированной запятой в информатике! Независимо от того, как они хранятся под капотом, ключевым моментом является следующее:

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

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

Плавающие палочки 🦋

Вот такие забавные!

Вспомните нашу оригинальную мерную линейку во всей ее великолепной длине в 1 метр. Но на этот раз давайте изменим то, как мы тратим наши 1000 марок. Вместо того, чтобы ставить одну отметку через каждую 1/1000 длины линейки, что, если MeSticks будет делать отметку на все более удаленных расстояниях?

На новой линейке вы можете увидеть две четкие отметки с обеих сторон, на которых написано «0 м» и «1 м». И, как и раньше, вы можете видеть отметки каждые 10 см, например 10 см, 20 см, 30 см и т. Д. Но если вы посмотрите на 36,7 см, их просто нет. Вы должны выбрать 30 см или 40 см. Между ними нет никакой маркировки.

Однако, посмотрев налево, вы заметите, что все еще есть отметки от 0 до 10 см, через каждые 1 сантиметр. А еще левее - миллиметровые отметки от 0 до 1 см.

Но есть кое-что еще. Взяв увеличительное стекло, вы можете увидеть 10 четких меток от 0 до 1 мм, равномерно расположенных. У этой ширины нет научного названия (кроме 0,1 мм!), Поэтому мы будем называть ее шириной волоса, так как это прекрасно.

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

Есть еще две дополнительные, но невероятно важные детали, которые я упустил из-за этой измерительной ручки.

Во-первых, его длина на самом деле не превышает 1 м. Его длина составляет 100 м, и есть маркировка через каждые 1–10 м, а затем через каждые 10–100 м.

Во-вторых, это единственный тип Floating Stick MeSticks, который решили сделать. Мы не можем выбросить его и купить побольше или поменьше - это 100 метров, бери или оставляй!

Как и раньше, на палочке еще 1000 отметок, даже если многие из них слишком малы, чтобы мы могли их увидеть!

Давайте посмотрим на ценности, о которых мы говорили ранее.

Можем ли мы измерить 36,7 см? Нет, не можем, но можно округлить до ближайших 10 см, чтобы получить 40 см.

Можем ли мы измерить 242 см? Опять же, не совсем так - мы можем измерить 2 м, но для этого нам совсем не нужно было расширять стержень.

770см? Получится 8 м - опять же, расширение не требуется. Точно, но неточно.

Мы также рассмотрели 9,4 мм, для чего раньше требовалась линейка меньшего размера. Это можно измерить на нашей палке с плавающей запятой! Поскольку оно меньше 10 мм, и мы получаем точность 1/10 мм (или «ширину волоса»), да, мы можем указать это значение точно на нашей ручке.

Вы видите здесь закономерность?

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

Это ключевая идея чисел с плавающей запятой:

Числа с плавающей запятой меняют точность на большие числа для более широкого диапазона представимых значений.

Фиксированный vs плавающий 🥊

На этом этапе вы можете почувствовать, что числа с фиксированной точностью лучше, чем числа с плавающей запятой - в конце концов, посмотрите на все те полезные числа, которые мы не смогли правильно отобразить!

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

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

Второй ключевой момент, который аналогия с измерительной ручкой может не показать, - это то, что диапазон значений на самом деле намного больше, чем вы ожидаете. Обычно используемое число с плавающей запятой «двойной точности» может представлять значения как маленькие 2 × 10⁻³⁰⁰. Проще говоря, это выглядит примерно так:

0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002

И самое большое значение составляет около 2 × 10³⁰⁰, что выглядит так:

200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Эти числа настолько невероятно малы и велики, что человеческий мозг не может их правильно понять!

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

Для чисел «человеческого размера», скажем 100 см, мы могли бы указать с точностью до 100,00000000000001 см, что намного меньше ширины волоса.

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

(Это вовсе не означает, что некоторые программы не имеют законного использования для чисел с фиксированной запятой!)

Небольшая заметка о базах

Вы можете вспомнить, что ранее я указывал, что наши линейки были установлены в базе 10. Я говорю это, поскольку двоичные числа находятся в базе 2. Таким образом, вместо чисел с плавающей запятой, меняющих точность в точках 1, 10, 100, 1000, они будут изменить точность на 1, 2, 4, 8, 16.

Интересный эффект в видеоиграх и симуляторах

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

В этом видео вы можете увидеть, как в оригинальной версии Minecraft возникали странные ошибки, когда игрок уезжал слишком далеко от центра мира:

Это напрямую связано с тем фактом, что мы не можем хранить большие числа точно с помощью чисел с плавающей запятой!

Заключение 🐮

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

Отличное руководство для просмотра находится здесь: https://floating-point-gui.de/