Alex Barucchieri |
Continuo da qui con operazioni aritmetiche in Bash. In particolare la divisione, è trattata un po' troppo semplicemente, esempio (ediv):
N=$1
M=$2
echo $N '/' $M '=' $(( N / M ))
$ bash ediv 3 3
3 / 3 = 1
$ bash ediv 4 3
4 / 3 = 1
$ bash ediv 5 3
5 / 3 = 1
$ bash ediv 6 3
6 / 3 = 2
$
come si vede il risultato è sempre la parte intera, scartando il resto (modulo); in genere questa operazione è conosciuta come floor ma ci sono anche il round (arrotondamento) e il ceil, intero in eccesso.
Conviene, visto che ci sono ben 3 casi simili creare una libreria (parola grossa, e poi a rigore library si dovrebbe tradurre con biblioteca, ma è così da 70 anni) con le tre funzioni (def_div):
function floor() {
echo $(( $1 / $2 ))
}
function round() {
local Iden
Iden=$(( $2 / 2 ))
echo $(( $(( $1 + $Iden )) / $2 ))
}
function ceil() {
local R S
R=$(( $1 % $2 ))
S=$(( $1 / $2 ))
(( S = $R==0 ? S : S + 1 ))
echo $S
}
Per usarle basta richiamare la libreria (cioè questo file) nello script, esempio (f-div):
N=$1
M=$2
. def_div # carica la libreria con le funzioni
echo 'floor:' $(floor $N $M)
echo 'round:' $(round $N $M)
echo 'ceil :' $(ceil $N $M)
ed ecco:
$ bash f-div 9 3
floor: 3
round: 3
ceil : 3
$ bash f-div 10 3
floor: 3
round: 3
ceil : 4
$ bash f-div 11 3
floor: 3
round: 4
ceil : 4
$ bash f-div 12 3
floor: 4
round: 4
ceil : 4
$
Volendo si può fare anche meglio: calcolare il valore reale della divisione in Bash! L'hanno proposto in tanti, su Stack Overflow e altrove (chi ha copiato chi?), ecco div, file def_r_div:
function div {
local _d=${3:-2}
local _n=0000000000
_n=${_n:0:$_d}
local _r=$(($1$_n/$2))
_r=${_r:0:-$_d}.${_r: -$_d}
echo $_r
}
Il test (file t_div):
. def_r_div # carica la funzione div
echo "$1 / $2 =" $(div $*)
ottengo:
$ bash t_div 9 3
9 / 3 = 3.00
$ bash t_div 9 3 4
9 / 3 = 3.0000
$ bash t_div 10 3
10 / 3 = 3.33
$ bash t_div 11 3
11 / 3 = 3.66
$ bash t_div 12 3
12 / 3 = 4.00
$
sì, niente arrotondamento decimale, ma c'è anche un bug:
$ bash t_div 12 3 0
12 / 3 = .4
$
errore! la correzione non è difficile ma allunga il codice della funzione; lasciata come esercizio.
Piuttosto se si dovesse usare per più casi si può caricare la funzione in memoria, cosi:
$ source def_r_div
$ div 9 3
3.00
$ div 10 3
3.33
$ div 11 3 5
3.66666
$ div 12 3
4.00
$
La funzione resta in memoria nel terminale finché questo non viene chiuso. Per i vecchi come me questa cosa è (almeno un po') stupefacente: allora si sarebbe aperta una sub-shell all'interno della quale svolgere le elaborazioni e infine chiusa con ctrl-D (o exit), così:
$ div 12 3
Comando «div» non trovato, si intendeva forse: [...]
$ bash
$ source def_r_div
$ div 12 3
4.00
$ exit
exit
$ div 12 3
Comando «div» non trovato, si intendeva forse: ...
$
E sì, non sembra ma sono passati 30 anni (circa, troppi, non so contarli).
Ah! 'ncora una cosa: lo sappiamo tutti che l'aritmetica si può fare in molti altri modi, sovente più semplici, p.es. con Python, JavaScript o ______________. Ma anche (io farei così):
$ echo "scale=2; 22 / 7" | bc
3.14
$ echo "scale=4; 22 / 7" | bc
3.1428
$
🔴
Nessun commento:
Posta un commento