Come confrontare due valori in virgola mobile in script di shell
-
03-10-2019 - |
Domanda
ho dovuto fare una divisione in script di shell e il modo migliore era:
result1=`echo "scale=3; ($var1 / $total) * 100"| bc -l`
result2=`echo "scale=3; ($var2 / $total) * 100"| bc -l`
, ma voglio mettere a confronto i valori di $result1
e $result2
Utilizzando if test $result1 -lt $result2
o if [ $result1 -gt $result2 ]
non ha funzionato: (
Qualsiasi idea di come fare?
Soluzione
È possibile confrontare i numeri in virgola mobile utilizzando expr(1)
:
: nr@yorkie 3724 ; expr 3.1 '<' 3.3
1
: nr@yorkie 3725 ; expr 3.1 '<' 3.09
0
Si può anche avere bc
fare i confronti, nonché i calcoli:
if [ "$(echo $result1 '<' $result2 | bc -l)" -eq 1 ];then ... fi
Infine, ksh93 può fare aritmetica $(($result1 < $result2))
valutazione con numeri in virgola mobile, anche se non può bash.
Altri suggerimenti
Si noti che hai devo essere un po 'attenti quando si tratta di numeri in virgola mobile e se si esegue il test per l'uguaglianza si vuole veramente decidere su una certa precisione e quindi confrontare con quello. Qualcosa di simile:
if (abs(x1-x2) < 0.0001) then equal # pseudo-code
il motivo è che con i computer abbiamo a che fare con limitata precisione frazioni binario non veri reali matematici. Limitare la precisione in BC con la scala = 3 avrà questo effetto.
Mi piacerebbe anche consigliare contro cercando di fare questa roba in script di shell. Non è che non si può fare, ma si dovrà sborsare fuori un sacco di comandi poco sotto a fare i bit difficili e questo è lento da eseguire e in generale un dolore alla scrittura - passi la maggior parte del vostro tempo cercando di ottenere il guscio per fare ciò che si vuole piuttosto che scrivere il codice che si vuole veramente. Drop in un linguaggio di scripting più sofisticato, invece; la mia lingua di scelta è perl, ma ce ne sono altri. così ...
echo $var1 $var2 $total | perl -ne 'my ($var1, $var2, $tot) = split /\s+/; if ($var1/$tot == $var2/$tot) { print "equal\n"; }'
Si noti inoltre che si sta dividendo per lo stesso valore ($ totale nella tua domanda) quindi l'intero confronto può essere fatto contro i numeratori (Q1 e VAR 2) fornito $ totale è positivo
La pubblicazione di un nuova risposta dal momento che non può ancora commentare ...
@Norman di Ramsey risposta ??a > non è abbastanza preciso:
-
expr
eseguirà un confronto interi o stringhe, non un confronto in virgola mobile.
Ecco cosa la pagina man dice:expr1 {=,>,> =, <, <=,! =} Espr2
Ritorna i risultati di confronto intero se entrambi gli argomenti sono interi; in caso contrario, restituisce i risultati di confronto tra stringhe utilizzando la sequenza di confronto specifica locale.
(solo cercare
expr 8.9 '<' 10
e ottenere0
dove dovrebbe essere1
). -
bc
works grandi, ma non è sempre installato.
Quindi, un'altra alternativa utilizza perl -e
:
-
perl -e 'print expression'
viene stampata1
se espressione è vera e niente (stringa vuota) in caso contrario.es.
perl -e 'print 8.9 < 10'
-. stampe "1", mentre le stampeperl -e 'print 2>4'
niente -
E quando viene utilizzato in dichiarazione
if
:if [ $(perl -e "print $result1 < $result2") ];then ... fi