2016-07-12 2 views
4

Почему printf ведет себя так необычно?Почему printf (Unix) использует круглую половину?

> printf %.0f 2.5 
> 2 
> printf %.0f 2.51 
> 3 

Есть преимущество такого поведения, которое компенсирует возможные недопонимания (как this one)?

+0

bash printf, или UNIX (ака, ваша операционная система) printf? Это две разные команды: первая - это встроенная оболочка, а последняя - '/ usr/bin/printf' и не включает в себя встроенные bash, такие как'% q'. –

+4

Действительно ли это * округляется * или оно округляется до четного *? Последний более распространен, а для «2.5» две стратегии округления дают одинаковый результат. Попробуйте 'printf 3.5'. – delnan

+0

Я использовал/usr/bin/printf. –

ответ

4

Это не строго круглые вниз:

> printf '%.0f\n' 2.5 
2 
> printf '%.0f\n' 3.5 
4 

Это форма округления используется для борьбы с предвзятостью, если вы округлением большого количества значений; примерно половина из них будет округлена, другая половина округлена. Правило округляется, если целочисленная часть четная, вверх, если целочисленная часть является нечетной.


Это, однако, лишь объяснение конкретной схемы округления, которая не гарантированно будет использоваться всеми реализациями printf.

0

Из спецификации POSIX для команды printf:

с плавающей точкой спецификация преобразования форматирования Е() не требуется, поскольку все арифметические операции в оболочке целочисленная арифметика. Утилита awk выполняет вычисления с плавающей запятой и предоставляет собственную функцию printf. Утилита bc может выполнять арифметику с плавающей запятой произвольной точности, но не предоставляет расширенных возможностей форматирования. (Эта утилита printf не может использоваться для форматирования вывода bc, она не поддерживает произвольную точность.) Реализации рекомендуется поддерживать преобразования с плавающей запятой в качестве расширения.

Таким образом: %fдаже не требуется, чтобы существовать на всех; все, что оно может или не может сделать, полностью не определено соответствующим стандартом.


Кроме того, нет никаких указаний на округление при условии, по стандарту POSIX для printf() функции:

F, F

Двойной аргумент должен быть преобразован в десятичной системе счисления в стиле " [-] ddd.ddd ", где количество цифр после символа radix равно спецификации точности. Если точность отсутствует, она принимается равной 6; если точность явно равна нулю, а флаг '#' не присутствует, то не должно появляться символ счисления. Если появляется символ радикса, перед ним появляется как минимум одна цифра. Цифра низкого порядка округляется в соответствии с реализацией.

Двойной аргумент, представляющий бесконечность, должен быть преобразован в один из стилей «[-] inf» или «[-] бесконечность»; стиль которого определяется реализацией. Двойной аргумент, представляющий NaN, должен быть преобразован в один из стилей «[-] nan (n-char-sequence)» или «[-] nan»; какой стиль и значение любой n-char-последовательности, определяется реализацией. Спецификатор преобразования F создает «INF», «INFINITY» или «NAN» вместо «inf», «infinity» или «nan», соответственно.

+0

Это действительно больше комментарий к вопросу; стандарты в стороне, «printf» OP (в зависимости от того, что он есть) * does * поддерживает '% f', и вопрос спрашивает о наблюдаемом поведении. – chepner

+0

Я поддержал ваш ответ - он * является отличным, но любой ответ о «почему» является неполным без обсуждения стандартов, если таковые имеются, для которых инструмент должен соответствовать, и соответствуют ли эти стандарты адресуйте поведение под рукой. –

+0

Я использовал эту утилиту printf для форматирования вывода bc, поэтому этот ответ мне тоже помогает! Теперь я буду использовать awk. –

Смежные вопросы