Точность плавающей точки C++ [дубликат]

7
задан Community 23 May 2017 в 11:51
поделиться

5 ответов

Чтобы получить правильные результаты, не устанавливайте точность выше, чем доступно для этого числового типа:

#include <iostream>
#include <limits>
int main()
{
        double a = 0.3;
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << a << std::endl;
        double b = 0;
        for (char i = 1; i <= 50; i++) {
                  b = b + a;
        };
        std::cout.precision(std::numeric_limits<double>::digits10);
        std::cout << b << std::endl;
}

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

16
ответ дан 6 December 2019 в 05:42
поделиться

Чтобы получить "правильный" результат, попробуйте

Список библиотек арифметики произвольной точности из Википедии: http://en.wikipedia.org/wiki/Arbitrary-precision

or

http://speleotrove.com/decimal

-2
ответ дан 6 December 2019 в 05:42
поделиться

Компьютеры хранят числа с плавающей запятой в двоичном, а не десятичном виде.

Многие числа, которые выглядят обычными в десятичной системе счисления, например 0,3, не имеют точного представления конечной длины в двоичной системе счисления.
Поэтому компилятор выбирает ближайшее число, которое имеет точное двоичное представление, точно так же, как вы пишете 0.33333 для 1⁄3.

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

7
ответ дан 6 December 2019 в 05:42
поделиться

Дело не в том, что оно больше или меньше, просто физически невозможно хранить "0.3" как точное значение внутри двоичного числа с плавающей точкой.

Способ получить "правильный" результат - не отображать 20 знаков после запятой.

1
ответ дан 6 December 2019 в 05:42
поделиться

Почему?

Поскольку числа с плавающей запятой хранятся в двоичном формате, в котором 0,3 равно 0,01001100110011001 ... повторение точно так же, как 1/3 равно 0,333333 ... повторение в десятичном формате. Когда вы пишете 0,3 , вы фактически получаете 0,299999999999999988897769753748434595763683319091796875 (бесконечное двоичное представление, округленное до 53 значащих цифр).

Имейте в виду, что для приложений, для которых предназначена плавающая точка, не проблема, что вы не можете точно представить 0,3. Плавающая точка была разработана для использования с:

  • физическими измерениями, которые часто измеряются только до 4 знаков и никогда не более чем 15.
  • Трансцендентные функции, такие как логарифмы и триггерные функции, которые в любом случае только приблизительны.

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

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

А как в этом случае получить правильный результат?

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

11
ответ дан 6 December 2019 в 05:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: