Как сравнить (длинные двойные) значения в C? - PullRequest
0 голосов
/ 16 декабря 2018

Вот мой код:

#include <stdio.h>
static long double   ft_ldmod(long double x, long double mod)
{
    long double res;
    long double round;
    res = x / mod;
    round = 0.0L;
    while (res >= 1.0L || res <= -1.0L)
    {
        round += (res < 0.0L) ? -1.0L : 1.0L;
        res += (res < 0.0L) ? 1.0L : -1.0L;
    }
    return ((x / mod - round) * mod);
}
int  main(void)
{
    long double x;
    long double r;
    x = 0.0000042L;
    r = ft_ldmod(x, 1.0L);
    while (r != 0.0L)  // <-- I have an infinite loop here
    {
        x *= 10.0L;
        r = ft_ldmod(x, 1.0L);
    }
    printf("%Lf", x);
    return (0);
}

Кажется, что-то не так, но не могу понять это.Цикл while в основной функции зацикливается и не прерывается.Даже условие ложное, оно просто прошло ... Помощь приветствуется, спасибо.

1 Ответ

0 голосов
/ 16 декабря 2018

После x = 0.0000042L; значение x зависит от формата long double, используемого вашей реализацией на Си.Это может быть 4.2000000000000000001936105559186517000025418155928491614758968353271484375 • 10 −6 .Таким образом, в его десятичном представлении больше цифр, чем ожидает код в вопросе.Когда число многократно умножается на 10, оно становится большим.

По мере того, как оно увеличивается в миллионы и миллиарды, ft_ldmod становится все медленнее и медленнее, так как при подсчете находит желаемое значение roundна единицу.

Более того, даже если ft_ldmod достаточно времени, x и round со временем станут настолько большими, что добавление единицы к round не даст никакого эффекта.То есть для представления большого значения round в long double потребуется показатель степени, настолько большой, что младший бит, используемый для представления round в long double, представляет значение 2.

По сути,Программа в корне ошибочна как способ найти десятичное представление x.Кроме того, в операторе x *= 10.0L; возникнут ошибки округления, поскольку точный математический результат умножения числа на десять часто не совсем точно представляется в long double, поэтому он округляется до ближайшего представимого значения.(Это похоже на умножение на 11 в десятичном виде. Начиная с 1, мы получаем 11, 121, 1331, 14641 и т. Д. Количество цифр растет. Аналогично, умножение на десять в двоичном виде увеличивает количество значащих бит.)

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