2013-02-13 17 views
14

Ich möchte zwei Zahlen in awk unter Verwendung von Ganzzahl-Division, d. H. Abgeschnitten das Ergebnis. Zum BeispielInteger-Division in awk

k = 3/2 
print k 

sollte 1

Nach the manual,

Abteilung drucken; weil alle Zahlen in awk sind Gleitkommazahlen, ist das Ergebnis nicht

Gibt es eine Abhilfe zu bekommen einen ganzzahligen Wert auf eine ganze Zahl gerundet?

Der Grund dafür ist, dass ich das mittlere Element eines Arrays mit integer Indizes [0 bis num-1] erhalten möchten.

Antwort

27

über die int Funktion den ganzzahligen Teil des Ergebnisses erhalten, abgeschnitten zu 0. Dies erzeugt die nächste Ganzzahl zu dem Ergebnis, das zwischen dem Ergebnis und 0. Zum Beispiel int(3/2) 1 ist, int(-3/2) -1.

Quelle: The AWK Manual - Numeric Functions

4

In einfachen Fällen können Sie sicher int() verwenden, die gegen Null kürzt:

awk 'BEGIN { print int(3/2) }' # prints 1 
gawk 'BEGIN { print int(-3/2) }' # prints -1; not guaranteed in POSIX awk 

Beachten Sie, dass immer awk verwendet doppelter Genauigkeit Gleitkommazahlen und Fließkomma-Arithmetik , obwohl. Die einzige Möglichkeit, Ganzzahlen und Ganzzahlarithmetik zu erhalten, besteht darin, externe Werkzeuge zu verwenden, z. der Standard-expr Dienstprogramm:

awk 'BEGIN { "expr 3/2" | getline result; print result; }' # prints 1 

Das ist wirklich awk Station, lange, langsame, ... aber sicher und tragbar.


In POSIX awk wird Trunkierung auf Null für positive Argumente nur dann gewährleistet: int (x) - das Argument auf eine ganze Zahl gekürzt zurückzukehren. Die Abschneidung soll gegen 0 gehen, wenn x> 0 ist.GNU awk (gawk) verwendet Trunkierung in Richtung Null auch für negative Zahlen: int (x) - Gibt die nächste Ganzzahl an x ​​zurück, die sich zwischen x und null befindet und gegen Null abgeschnitten ist. Zum Beispiel ist int (3) 3, int (3,9) ist 3, int (-3,9) ist -3, und int (-3) ist ebenfalls -3.Numerische Ausdrücke werden in POSIX als Expressions in awk mit doppelter Genauigkeit angegeben.
Alle Arithmetik wird die Semantik von Gleitkomma-Arithmetik wie spezifiziert durch die ISO-C-Standard (siehe Concepts Derived from the ISO C Standard) folgen. - POSIX awk: Arithmetic functions


Wenn Sie Schwimmer verwenden, sollten Sie über ihre Macken kennen und bereit sein, sie zu entdecken und damit verbundene Fehler zu vermeiden. Mehrere beängstigend Beispiele:

  • nicht darstellbare Zahlen:

    awk 'BEGIN { x = 0.875; y = 0.425; printf("%0.17g, %0.17g\n", x, y) }' 
    # prints 0.875, 0.42499999999999999 
    
  • Round-off errors Akkumulation:

    awk 'BEGIN{s=0; for(i=1;i<=100000;i++)s+=0.3; printf("%.10f, %d\n",s,int(s))}' 
    # prints 29999.9999999506, 29999 
    
  • Rundungsfehler ruinieren Vergleiche:

    awk 'BEGIN { print (0.1 + 12.2 == 12.3) }' # prints 0 
    
  • Precision nimmt mit Größe, was zu Endlosschleifen:

    awk 'BEGIN { for (i=10^16; i<10^16+5; i++) printf("%d\n", i) }' 
    # prints 10000000000000000 infinitely many times 
    

Lesen Sie mehr darüber, wie schwimmt Arbeit:

  1. Stack-Überlauf-Tags wiki

  2. Wikipedia-Artikel Floating point

  3. GNU awk arbitrary precision arithmetic - enthält sowohl Informationen über die konkrete Umsetzung und Allgemeinwissen

+0

Ich denke, eine Möglichkeit, die schwimmenden Fehler zu überwinden (für relativ kleine Zahlen) wäre "int (3/2 + 0,25)". – user000001

+0

@ user000001 Das Hinzufügen einer Konstante löst das Problem nicht, es fügt tatsächlich ein neues hinzu. 'awk 'BEGIN {print int (7/8), int (7/8 + 0,25)}' erzeugt '0 1'. – Palec

+0

Ja, es müsste kleiner sein als '1/(d/2)', wobei "d" der Nenner ist. Solange dieser Wert größer als der Floating-Fehler ist, sollte es funktionieren. – user000001

5

Sicher und schnell awk Integer-Division kann gemacht werden:

q=(n-n%d)/d+(n<0) 
+0

+1. Cleverer Trick, ich gebe dir das. Ich frage mich, ob es für Präzisionsfehler sicher ist, wie @Palec erklärt ... – user000001

+0

+1 Dies implementiert eine 'ceil' Art der Rundung (in Richtung + inf). Andere mathematisch korrekte Mod-Konzepte und folglich Rundungsmethoden existieren. Eine andere Methode mag vorzuziehen sein. – sorontar

+0

@sorontar Zumindest in meinem System ist dies nicht gleichbedeutend mit einer Ceil-Funktion –