тип литья длинный двойной длинный - PullRequest
0 голосов
/ 05 мая 2019

Я делаю приведение типов в C следующим образом

long double dec = 12.32;
long double n = dec - (long long)dec;

когда я печатаю 6 цифр n после точки "." предполагая, что n равно 0,32, это дает мне 3, 1, 9, 9, 9, 9; но когда я делаю этот акт

double n = dec - (int)dec;

печать правильная (3, 2, 0, 0, 0, 0), и я не могу понять, почему

Код печати всего лишь:

for (int i = 0; i < 6; i++)
{
   n *= 10;
   printf("%d digit = %d or %lld\n", i, (int) or (long long)n);
   n -= (int) or (long long)n;
}

Ответы [ 2 ]

3 голосов
/ 05 мая 2019

12.32 не представляется в форматах, которые ваша реализация C использует для long double или double.

Ближайшее представимое значение до 12,32 в long double может быть 12,319999999999999999722444243843710864894092082977294921875. Это частично объясняет, почему ваша программа показывает 3, 1, 9, 9, 9 и 9 - это действительные десятичные цифры числа.

Аналогично, ближайшим представимым значением 12,32 в double может быть 12,32000000000000028421709430404007434844970703125, и это объясняет, почему ваша программа показывает 3, 2, 0, 0, 0 и 0.

Однако в показанном вами коде long double dec = 12.32;, 12.32 является константой double. Он должен иметь значение double, даже если вы присваиваете ему значение long double. Так что это не объясняет, почему ваша программа показывает 3, 1, 9, 9, 9 и 9. Вам потребуется суффикс l, чтобы сделать его константой long double, как в long double dec = 12.32l;. Возможно, код, который вы показываете в вопросе, не совсем тот код, который вы использовали для создания 3, 1, 9, 9, 9 и 9.

Кроме того, код n *= 10; не может использоваться для извлечения цифр. Это связано с тем, что в общем случае математический результат умножения значения double или long double на 10 не представляется в формате double или long double - поскольку для представления 10 требуется три значащих бита (101 ) 2 • 2 1 ), для точного произведения могут потребоваться более значимые биты, чем в double. Как следствие, точный математический результат округляется, чтобы соответствовать формату с плавающей запятой. Другими словами, n *= 10; меняет значение; он не просто умножает его на 10. Поэтому он не всегда будет давать цифры исходного числа.

0 голосов
/ 05 мая 2019

Работает нормально.Но у вашего кода много проблем:

for (int i = 0; i++; i < 6) не делает то, что вы думаете :) (см. Мой ответ)

printf long long требует %lld, и если вы используете%d это неопределенное поведение

void foo(long double dec)
{
    long double n = dec - (long long)dec;

    for (int i = 0; i< 6; i++)
    {
        n *= 10;
        printf("%d digit = %lld\n", i, (long long)n);
        n -= (long long)n;
    }

    printf("%lld\n", (long long)(n * 100)); 
}

int main()
{
    foo(12.32);

    return 0;
}

https://ideone.com/DGvPQJ

РЕДАКТИРОВАТЬ

Похоже, ваш компилятор использует только числа с плавающей запятой, а не double или long double

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