2016-07-12 2 views
4

Warum verhält sich printf so ungewöhnlich?Warum verwendet printf (Unix) runde Halbtöne?

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

Gibt es ein Vorteil dieses Verhalten, das die möglichen Missverständnisse (wie this one) kompensiert?

+0

bash printf oder UNIX (auch das Betriebssystem) printf? Sie sind zwei verschiedene Befehle - der erste ist eine eingebaute Shell, während der zweite '/ usr/bin/printf' ist und keine bash-eingebauten wie'% q' enthält. –

+4

Richtig * Abrunden * oder * Runden * bis *? Letzteres ist üblicher, und für "2,5" ergeben die beiden Rundungsstrategien das gleiche Ergebnis. Versuchen Sie 'printf 3.5'. – delnan

+0

Ich benutzte/usr/bin/printf. –

Antwort

4

Es ist nicht streng Abrundungs:

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

Dies ist eine Form verwendet Rundungs ​​Bias zu bekämpfen, wenn Sie eine große Anzahl von Werten gerundet werden; ungefähr die Hälfte von ihnen wird abgerundet, die andere Hälfte wird abgerundet. Die Regel ist, abgerundet, wenn der ganzzahlige Teil gerade ist, aufwärts, wenn der ganzzahlige Teil ungerade ist.


Dies ist jedoch nur eine Erklärung einer bestimmten Rundungsregelung, die nicht von allen Implementierungen von printf verwendet werden gewährleistet.

0

Aus der POSIX-Spezifikation für den Befehl printf:

Die Umwandlung Formatierungs Gleitkommazahl Spezifikationen printf() nicht, weil alle Arithmetik Integer-Arithmetik in der Schale erforderlich ist. Das Dienstprogramm awk führt Gleitkommaberechnungen durch und stellt eine eigene printf-Funktion bereit. Das Dienstprogramm bc kann Gleitkommaarithmetik mit beliebiger Genauigkeit ausführen, bietet jedoch keine umfangreichen Formatierungsfunktionen. (Dieses printf-Dienstprogramm kann nicht wirklich zum Formatieren der bc-Ausgabe verwendet werden; es unterstützt keine willkürliche Genauigkeit.) Implementierungen werden empfohlen, die Fließkomma-Konvertierungen als Erweiterung zu unterstützen.

So: %fist nicht einmal bei allen existieren erforderlich; alles, was es tun oder nicht tun kann, ist durch den relevanten Standard völlig unspezifiziert.


Ebenso gibt es keine Anleitung für die printf() Funktion auf dem POSIX-Standard zur Verfügung gestellt Runden:

f, F

Das doppelte Argument wird im Stil Dezimalschreibweise umgewandelt werden " [-] ddd.ddd ", wobei die Anzahl der Ziffern nach dem Radix-Zeichen der Genauigkeitsspezifikation entspricht. Wenn die Genauigkeit fehlt, wird sie als 6 angenommen; Wenn die Genauigkeit explizit Null ist und kein "#" - Flag vorhanden ist, sollte kein Radix-Zeichen erscheinen. Wenn ein Radix-Zeichen erscheint, erscheint mindestens eine Ziffer davor. Die niederwertige Zahl soll in einer implementierungsdefinierten Weise gerundet werden.

Ein Doppelargument, das eine Unendlichkeit darstellt, soll in einem der Stile "[-] inf" oder "[-] infinity" konvertiert werden; Welcher Stil ist implementierungsdefiniert? Ein Doppelargument, das ein NaN darstellt, soll in einem der Stile "[-] nan (n-char-sequenz)" oder "[-] nan" umgewandelt werden; welcher Stil und die Bedeutung einer beliebigen n-char-Sequenz ist implementierungsdefiniert. Der F-Konvertierungsspezifizierer erzeugt "INF", "INFINITY" oder "NAN" anstelle von "inf", "infinity" bzw. "nan".

+0

Das ist wirklich mehr ein Kommentar zu der Frage; Abgesehen von den Standards unterstützt das "printf" des OP (je nachdem, was es ist) *% f, und die Frage fragt nach dem beobachteten Verhalten. – chepner

+0

Ich habe Ihre Antwort aufgefrischt - sie ist * eine ausgezeichnete - aber jede Antwort auf "warum" ist unvollständig ohne eine Diskussion der Standards, falls vorhanden, zu denen ein Werkzeug verpflichtet ist, sich anzupassen, und ob diese Standards das vorliegende Verhalten ansprechen. –

+0

Ich benutzte dieses printf-Dienstprogramm, um bc-Ausgabe zu formatieren, so dass diese Antwort mir auch hilft! Ich werde jetzt stattdessen awk verwenden. –