Как точно отобразить десятичные цифры двойного в C ++? - PullRequest
5 голосов
/ 11 июля 2011

Задача
Даны два целых числа a, b, a Пример ввода
3 7
345 800
112 990
53 122

Пример вывода
.428751
Последние 6 цифр повторяются навсегда.
.43125
Это расширение прекращается.
.113
Последние 2 цифры повторяются вечно.
.4344262295081967213114754098360655737704918032786885245901639
Последние 60 цифр повторяются навсегда.

Примечание. Эта проблема является исходной для конкурса программ ProgFest.

Алгоритм этой задачи не сложен, если мы применим эти три теоремы: enter image description here

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

void displayFraction( int n, int d, int length ) {
    std::cout << ".";
    double alpha = static_cast<double>( n ) / d;
    for( int i = 1; i <= length; ++i ) {
        int c = std::floor( 10.0 * alpha );
        alpha = 10.0 * alpha - c;
        std::cout << c;
    }
}

И мой вывод был:

.4344 2622 9508 1967 3732 7807 5683 6291 4025 7835 3881 8359 3750 0000 0000 0

, где вывод проблемы был:

.4344 2622 9508 1967 2131 1475 4098 3606 5573 7704 9180 3278 6885 2459 0163 9

Как вы можете видеть, это было верно до 16-й цифры.Поэтому мой вопрос заключается в том, как я могу предотвратить усечение цифр при выполнении вычисления в этой конкретной ситуации?Есть идеи?

Ответы [ 3 ]

4 голосов
/ 11 июля 2011

Проблема в том, что double не имеет бесконечной точности, но может обрабатывать только около 16 десятичных цифр. Вот где вы столкнетесь с неприятностями (забавно, что!), Так как обнаруживается фундаментальный недостаток информации во входных данных double.

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

2 голосов
/ 11 июля 2011

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

Что-то вроде GNU MP Bignum , хотя доступны и другие варианты

2 голосов
/ 11 июля 2011

Используйте библиотеку bignum, например gmp . Там только так много информации, которую вы можете упаковать в двойной.

...