Как функции отображения, такие как sprintf, преобразовывают числа в строки? - PullRequest
1 голос
/ 23 февраля 2009

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

У меня есть такой код для извлечения дробной части:

double number = 2.01;
int frac = int(floor(number * 100)) % 100;

Однако результат здесь вместо 1 получается как 0. Это происходит потому, что исходный дубль фактически сохраняется как:

2.0099999...

Однако при запуске sprintf такое преобразование выглядит корректно:

char num_string[99];
sprintf(num_string,"%f",number);

Как sprintf получает правильный ответ, а вышеописанный метод - нет?

Ответы [ 2 ]

2 голосов
/ 23 февраля 2009

> Однако результат здесь вместо 1 получается как единое целое.

Что ты имеешь в виду?

2,099999 ...

Или, больше похоже на 2.00999...

Как вы уже заметили:

int frac = int(floor(number * 100)) % 100;

будет:

int frac = int(floor(2.00999... * 100)) % 100;
         = int(floor(200.999...)) % 100;
         = int(floor(200.999...)) % 100;
         = int(200) % 100;
         = 200 % 100;
         = 0;

Вас может заинтересовать this .

Также см. modf из math.h:

double modf(double x, double *intptr) /* Breaks x into fractional and integer parts. */ 

modf () - лучшая альтернатива, чем жонглирование самостоятельно.

1 голос
/ 23 февраля 2009

Я согласен с Dirkgently об использовании modf из math.h. Но если вы должны сделать жонглирование самостоятельно, попробуйте этот код. Это должно обойти проблему, которую вы видите.

int round(double a) {
    if (a > 0)
        return int(a + 0.5);
    else
        return int(a - 0.5);
}

int main()
{
    double number = 2.01;
    int frac = round((number - ((int)number)) * 100);
    printf("%d", frac);
}
...