Представляется ли значение с плавающей запятой 0,0 отличным от других значений с плавающей запятой? - PullRequest
0 голосов
/ 17 апреля 2020

Я возвращался к своей книге по C ++ и наткнулся на утверждение, в котором говорится, что ноль может быть представлен точно как число с плавающей запятой. Мне было интересно, как это возможно, если значение 0.0 не хранится как тип, отличный от значения с плавающей запятой. Я написал следующий код, чтобы проверить это:

#include <iomanip>
#include <iostream>

int main()
{
    float value1 {0.0};
    float value2 {0.1};

    std::cout << std::setprecision(10) << std::fixed;

    std::cout << value1 << '\n' 
              << value2 << std::endl;
}

Запуск этого кода дал следующий вывод:

0.0000000000
0.1000000015

До 10 цифр точности 0,0 все еще равно 0, а 0,1 имеет некоторое неточности (чего и следовало ожидать). Отличается ли значение 0,0 от других чисел с плавающей точкой тем, как оно представлено, и является ли это особенностью компилятора или архитектуры компьютера?

Ответы [ 2 ]

3 голосов
/ 17 апреля 2020

Как можно представить 2 как точное число? 4? 15? 0,5? Ответ только в том, что некоторые числа могут быть представлены точно в формате с плавающей запятой (который основан на base-2 / binary), а другие не могут.

Это ничем не отличается от десятичного. Вы не можете представить 1 / 3 точно в десятичном формате, но это не значит, что вы не можете представить 0.

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

Итак:

что это за значения (0, 1/16, 1/2048, ...), что позволяет им быть точно представленными .

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

Вы можете играть в онлайн с H. IEEE-754 Шмидта конвертер с плавающей точкой для разных чисел, чтобы увидеть кучу разных представлений, и какие ошибки возникают в результате кодирования в эти представления. Для начала попробуйте 0,5, 0,2 и 0,1.

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

Нет, абсолютно нет.

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

Но, если вы действительно знаете ошибку (или ее отсутствие), связанную с каждым шагом в создании значения (например, «все, что я сделал, инициализировал его к нулю»), тогда это нормально! Не нужно об этом беспокоиться.

2 голосов
/ 17 апреля 2020

Вот один из способов взглянуть на ситуацию: для сохранения числа в 64 битах существует 2^64 битовая комбинация. Некоторые из них являются представлениями «не числа», но большинство шаблонов 2^64 представляют числа. Представленное число представляется точно, без ошибок. Это может показаться странным после изучения математики с плавающей точкой ; Впереди скрывается предостережение.

Однако, столь же огромен, как и 2^64, существует бесконечно много реальных чисел. Когда вычисление дает нецелочисленный результат, шансы довольно хороши, что ответом не будет число, представленное одним из шаблонов 2^64. Есть исключения. Например, 1/2 представлен одним из шаблонов. Если вы храните 0.5 в переменной с плавающей запятой, она на самом деле будет хранить 0.5. Давайте попробуем это для других знаменателей с одним ди git. (Примечание: я пишу дроби из-за их выразительной силы; я не собираюсь использовать целочисленную арифметику c.)

  • 1/1 - хранится в точности
  • 1/2 - сохраняется точно
  • 1/3 - не сохраняется точно
  • 1/4 - сохраняется точно
  • 1/5 - не сохраняется точно
  • 1/6 - не сохраняется точно
  • 1/7 - не сохраняется точно
  • 1/8 - сохраняется точно
  • 1/9 - не сохраняется точно

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...