wake-up-neo.net

Runde eine geteilte Zahl in Bash

Wie würde ich das Ergebnis aus zwei Zahlen teilen, z.

3/2

Wie wenn ich es tue 

testOne=$((3/2))

$ testOne enthält "1", wenn als Antwort von 3/2 = 1.5 auf "2" gerundet werden soll

43
Mint

Um das Abrunden der Arithmetik durchzuführen, fügen Sie einfach (denom-1) zum Zähler hinzu.

Beispiel, Abrunden:

N/2
M/5
K/16

Beispiel zum Abrunden:

(N+1)/2
(M+4)/5
(K+15)/16

Fügen Sie dem Zähler (denom/2) hinzu (die Hälfte wird gerundet):

(N+1)/2
(M+2)/5
(K+8)/16
68
Ben Voigt

Eine gute Lösung ist, die nächstgelegene Rundenanzahl zu erhalten 

var=2.5
echo $var | awk '{print int($1+0.5)}'

Die Logik ist einfach, wenn der Var-Dezimalwert kleiner als 0,5 ist. Der nächstliegende Wert ist der ganzzahlige Wert. Wenn der Dezimalwert größer als 0,5 ist, wird der nächste ganzzahlige Wert hinzugefügt, und da awk dann nur einen ganzzahligen Teil nimmt. Problem gelöst

29
Ashish

bash liefert kein korrektes Ergebnis von 3/2, da es keine Floating-Pt-Mathematik macht. Sie können Werkzeuge wie awk verwenden

$ awk  'BEGIN { rounded = sprintf("%.0f", 3/2); print rounded }'
2

oder bc

$ printf "%.0f" $(echo "scale=2;3/2" | bc)
2
25
ghostdog74

Wenn Sie eine ganzzahlige Division positiver Zahlen haben, die auf Null rundet, können Sie der Dividende eine kleinere Zahl als den Divisor hinzufügen, um sie aufzurunden.

Das heißt, X / Y durch (X + Y - 1) / Y ersetzen.

Beweis:

  • Fall 1: X = k * Y (X ist ein ganzzahliges Vielfaches von Y): In diesem Fall haben wir (k * Y + Y - 1) / Y, der sich in (k * Y) / Y + (Y - 1) / Y aufteilt. Der (Y - 1)/Y-Teil wird auf Null gerundet und der Quotient k bleibt erhalten. Genau das wollen wir: Wenn die Eingaben teilbar sind, möchten wir, dass die angepasste Berechnung immer noch den richtigen exakten Quotienten ergibt.

  • Fall 2: X = k * Y + m wobei 0 < m < Y (X ist kein Vielfaches von Y). In diesem Fall haben wir einen Zähler von k * Y + m + Y - 1 oder k * Y + Y + m - 1 und können die Division als (k * Y)/Y + Y/Y + (m - 1)/Y ausschreiben. Da 0 < m < Y, 0 <= m - 1 < Y - 1 und somit der letzte Begriff (m - 1)/Y auf Null geht. Wir bleiben mit (k * Y)/Y + Y/Y, was sich k + 1 ergibt. Dies zeigt, dass das Verhalten aufrundet. Wenn wir eine X haben, die ein k-Vielfaches von Y ist, wenn wir nur 1 hinzufügen, wird die Division auf k + 1 aufgerundet.

Aber diese Rundung ist extrem entgegengesetzt; Alle ungenauen Divisionen gehen von Null weg. Wie wäre es mit etwas dazwischen?

Dies kann erreicht werden, indem der Zähler mit Y/2 "grundiert" wird. Berechnen Sie statt X/Y(X+Y/2)/Y. Anstelle von Beweisen gehen wir auf diesen einen empirischen Weg:

$ round()
> {
>   echo $((($1 + $2/2) / $2))
> }
$ round 4 10
0
$ round 5 10
1
$ round 6 10
1
$ round 9 10
1
$ round 10 10
1
$ round 14 10
1
$ round 15 10
2

Wenn der Divisor eine gerade, positive Zahl ist und der Zähler auf die Hälfte dieser Zahl kongruent ist, wird der Zähler aufgerundet, und der Wert wird abgerundet, wenn er um eins kleiner ist.

Zum Beispiel geht round 6 12 zu 1, ebenso wie alle Werte, die gleich 6 sind, modulo 12, wie 18 (was zu 2 geht) und so weiter. round 5 12 geht zu 0 über.

Bei ungeraden Zahlen ist das Verhalten korrekt. Keine der genauen rationalen Zahlen liegt in der Mitte zwischen zwei aufeinanderfolgenden Vielfachen. Mit einem Nenner von 11 haben wir beispielsweise 5/11 < 5.5/11 (exact middle) < 6/11; und round 5 11 rundet ab, während round 6 11 aufrundet.

8
Kaz

Zum Abrunden können Sie den Modulus verwenden.

Der zweite Teil der Gleichung wird zu True hinzugefügt, wenn ein Rest vorhanden ist. (True = 1; False = 0)

ex: 3/2

answer=$(((3 / 2) + (3 % 2 > 0)))
echo $answer
2

ex: 100/2

answer=$(((100 / 2) + (100 % 2 > 0)))
echo $answer
50

zB: 100/3

answer=$(((100 / 3) + (100 % 3 > 0)))
echo $answer
34
4
sk8asd123

Mit einem Gleitkommawert können wir ihn mit printf trivial runden:

# round $1 to $2 decimal places
round() {
    printf "%.2f" "$1"
}

Dann,

# do some math, bc style
math() {
    echo "$*" | bc -l
}

$ echo "Pi, to five decimal places, is $(round $(math "4*a(1)") 5)"
Pi, to five decimal places, is 3.14159

Oder verwenden Sie die ursprüngliche Anfrage:

$ echo "3/2, rounded to the nearest integer, is $(round $(math "3/2") 0)"
3/2, rounded to the nearest integer, is 2
4
N. Ingersoll

Eine andere Lösung besteht darin, die Division innerhalb eines Python-Befehls auszuführen. Zum Beispiel:

$ numerator=90
$ denominator=7
$ python -c "print (round(${numerator}.0 / ${denominator}.0))"

Scheint mir weniger archaisch als die Verwendung von awk.

2
Sean Staats

Wenn das Dezimaltrennzeichen ein Komma ist (zB: LC_NUMERIC = fr_FR.UTF-8, siehe hier ):

$ printf "%.0f" $(echo "scale=2;3/2" | bc) 
bash: printf: 1.50: nombre non valable
0

Die ghostdog74-Lösung muss ersetzt werden:

$ printf "%.0f" $(echo "scale=2;3/2" | bc | sed 's/[.]/,/')
2

oder

$ printf "%.0f" $(echo "scale=2;3/2" | bc | tr '.' ',')
2
1
Q-D

Ich denke das sollte genug sein.

$ echo "3/2" | bc 
1
guest

Folgendes arbeitete für mich.

 #!/bin/bash
function float() {
bc << EOF
num = $1;
base = num / 1;
if (((num - base) * 10) > 1 )
    base += 1;
print base;
EOF
echo ""
}

float 3.2
0
xs2rashid