Berechnung des gerundeten Prozentsatzes in Shell Script ohne Verwendung von "bc"

10

Ich versuche, den Prozentsatz bestimmter Elemente in Shell Script zu berechnen. Ich möchte den Wert abrunden, das heißt, wenn das Ergebnis 59,5 ist, sollte ich 60 und nicht 59 erwarten.

%Vor%

Dies ergibt 42.

Aber tatsächlich ist das Ergebnis 42,8 und ich würde es auf 43 runden. "bc" macht den Trick, gibt es einen Weg ohne "bc" zu benutzen?

Ich bin nicht berechtigt, neue Pakete zu installieren. "dc" und "bc" sind in meinem System nicht vorhanden. Es sollte reine Shell sein, kann Perl- oder Python-Skripte nicht verwenden

    
user2354302 18.06.2014, 11:34
quelle

4 Antworten

20

Verwende AWK (keine Bash-Ismen):

%Vor%     
Michael Back 19.06.2014, 05:16
quelle
6

Nimmt man 2 * die ursprüngliche Prozentberechnung und erhält man den Modulo 2 davon, wird das Inkrement zum Runden bereitgestellt.

%Vor%

(getestet mit Bash, Ash, Dash und Ksh)

Dies ist eine schnellere Implementierung als das Abfeuern eines AWK-Coprozesses:

%Vor%     
Michael Back 29.10.2015 08:21
quelle
4

Ein POSIX-kompatible Shell-Skript ist beschränkt auf integer Arithmetik mit der Shell-Sprache (" nur lange integer-Arithmetik unterzeichnete erforderlich ist "), so dass rein Shell Lösung muss emulieren Gleitkommazahlen Arithmetik:

%Vor%
  • 100 * item / total liefert das abgeschnittene Ergebnis der Division ganze Zahl als Prozentsatz.
  • 1000 * item / total % 10 >= 5 ? 1 : 0 berechnet die 1. Dezimalstelle, und wenn sie gleich oder größer als 5 ist, addiert man 1 zum ganzzahligen Ergebnis, um es aufzurunden.
  • Beachten Sie, dass no benötigt wird, um Variablenreferenzen mit $ in einer arithmetischen Erweiterung $((...)) voranzuzfügen.

Wenn - im Gegensatz zur Prämisse der Frage - die Verwendung von externen Dienstprogrammen akzeptabel ist:

  • awk bietet eine einfache Lösung, die jedoch mit dem caveat versehen ist, dass sie echte binäre Gleitkommawerte mit doppelter Genauigkeit und may verwendet daher ergeben unerwartete Ergebnisse in dezimal Darstellung - zB versuchen printf '%.0f\n' 28.5 , die Ausbeuten 28 anstatt der erwarteten 29 ):
%Vor%
  • Beachten Sie, wie -v verwendet wird, um Variablen für das Skript awk zu definieren, das eine saubere Trennung zwischen dem einfach zitierten und daher Literal % co_de ermöglicht % Skript und alle Werte, die von der Shell an übergeben werden.
  • Im Gegensatz dazu, obwohl awk ist ein POSIX-Dienstprogramm (und daher zu erwarten, kann auf den meisten Unix-ähnlichen Plattformen sein) und führt beliebiger Genauigkeit Arithmetik, es immer Verkürzungen die Ergebnisse, so dass Rundung muss von einem anderen -Dienstprogramm ausgeführt werden; aber bc , obwohl es ist ein POSIX-Dienstprogramm im Prinzip , ist nicht erforderlich zur Unterstützung von Fließkommaformatbezeichnern (wie in printf oben verwendet), so dass das folgende funktioniert oder nicht funktioniert (und ist angesichts der einfacheren Methode nicht die Mühe wert awk solution, und da die Genauigkeitsprobleme aufgrund der Fließkomma-Arithmetik wieder im Bild sind):
%Vor%     
mklement0 31.05.2016 02:52
quelle
0

Das Folgende basiert auf meiner zweiten Antwort, aber mit expr und Back-Ticks - die (vielleicht auch abscheulich für die meisten) angepasst werden können, um in even zu arbeiten die archaischsten Muscheln nativ:

%Vor%     
Michael Back 30.05.2016 20:39
quelle

Tags und Links