поведение округления printf для двойников

может кто-нибудь объяснить такое поведение? Я хорошо знаю машинное представление чисел с плавающей запятой. Это, по-видимому, связано с printf и его форматами. Оба числа представлены точно нотацией с плавающей запятой (проверка: умножение на 64 дает целое число).

#include <stdio.h>
#include <iostream>
using namespace std;

int main() {
  double x1=108.765625;
  printf("%34.30f\n", x1);
  printf("%9.5f\n", x1);
  printf("%34.30f\n", x1*64);

  double x2=108.046875;
  printf("%34.30lf\n", x2);
  printf("%9.5f\n", x2);
  printf("%34.30f\n", x2*64);
}

выход:

> 108.765625000000000000000000000000
> 108.76562
> 6961.000000000000000000000000000000
> 108.046875000000000000000000000000
> 108.04688
> 6915.000000000000000000000000000000

обратите внимание, что первое число округляется вниз, а второе округляется вверх.

2 ответов


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

http://linuxgazette.net/144/misc/lg/a_question_of_rounding_in_issue_143.html:
"Для библиотеки GNU C правилом округления, используемым printf (), является "округление банкиров" или "округление до четного". Это более правильно, чем некоторые другие библиотеки C, поскольку спецификация C99 говорит, что преобразование в decimal должен использовать текущий выбранный режим округления IEEE (округление банкиров по умолчанию)."


на %9.5f output дает число с 5 цифрами после десятичной точки, которая является ближайшей к исходному номеру.