Скругление удваивается - .5 - sprintf - PullRequest
9 голосов
/ 15 июня 2009

Я использую следующий код для округления до 2dp:

sprintf(temp,"%.2f",coef[i]); //coef[i] returns a double

Он успешно округляет 6,666 до 6,67, но не работает должным образом при округлении 5,555. Он возвращает 5,55, тогда как должен (по крайней мере, на мой взгляд) возвращать 5,56.

Как получить округление, когда следующая цифра 5? то есть вернуть 5,56.

edit: теперь я понимаю, что это происходит, потому что когда я ввожу 5.555 с cin, он получает сохранен как 5.554999997.

Я собираюсь попробовать округлить в два этапа - сначала до 3dp, а затем до 2dp. любой другой (более элегантные) идеи?

Ответы [ 5 ]

11 голосов
/ 15 июня 2009

Число 5.555 не может быть представлено как точное число в IEEE754. Распечатка константы 5.555 с "%.50f" приводит к:

5.55499999999999971578290569595992565155029300000000

так что будет округляться в меньшую сторону. Попробуйте использовать это вместо:

printf ("%.2f\n",x+0.0005);

хотя вам нужно быть осторожным с числами, которые могут точно представлять , так как они будут ошибочно округлены этим выражением.

Вы должны понимать ограничения представлений с плавающей точкой. Если важно, чтобы вы получили точность, вы можете использовать (или кодировать) BCD или другой десятичный класс, который не имеет недостатка представления IEEE754.

11 голосов
/ 15 июня 2009

Кажется, вы должны использовать математическую функцию округления для правильного округления.

printf("%.2f %.2f\n", 5.555, round(5.555 * 100.)/100.);

Это дает следующий вывод на моей машине:

5.55 5.56
2 голосов
/ 24 июня 2009

Как насчет другого возможного решения:

printf("%.2f", _nextafter(n, n*2));

Идея состоит в том, чтобы увеличить число от нуля (n * 2 получает знак справа) на наименьшую возможную величину, представленную математикой с плавающей запятой.

Например:

double n=5.555;
printf("%.2f\n", n);
printf("%.2f\n", _nextafter(n, n*2));
printf("%.20f\n", n);
printf("%.20f\n", _nextafter(n, n*2));

С выходом MSVC:

5.55
5.56
5.55499999999999970000
5.55500000000000060000
1 голос
/ 15 июня 2009

Этот вопрос помечен C ++, поэтому я буду исходить из этого предположения. Обратите внимание, что потоки C ++ будут округляться, в отличие от семейства C printf. Все, что вам нужно сделать, это обеспечить точность, которую вы хотите, и библиотека потоков будет округлена для вас. Я просто добавлю это на тот случай, если у вас еще нет причин не использовать потоки.

0 голосов
/ 15 июня 2009

Вы также можете сделать это (сохраняет умножение / деление):

printf("%.2f\n", coef[i] + 0.00049999);
...