Comment pourrais-je arrondir le résultat de deux nombres divisés, par exemple.
3/2
Comme quand je le fais
testOne=$((3/2))
$ testOne contient "1" alors qu'il aurait dû être arrondi à "2" comme réponse de 3/2 = 1.5
Pour arrondir en arithmétique tronquant, il suffit d’ajouter (denom-1)
au numérateur.
Exemple, arrondi au bas:
N/2
M/5
K/16
Exemple, en arrondissant:
(N+1)/2
(M+4)/5
(K+15)/16
Pour arrondir au plus proche, ajoutez (denom/2)
au numérateur (les moitiés seront arrondies au maximum):
(N+1)/2
(M+2)/5
(K+8)/16
La bonne solution est d’obtenir le numéro de tour le plus proche:
var=2.5
echo $var | awk '{print int($1+0.5)}'
La logique est simple si la valeur décimale var est inférieure à 0,5 alors la valeur la plus proche prise est la valeur entière. Eh bien, si la valeur décimale est supérieure à 0,5, la valeur entière suivante est ajoutée et depuis awk, elle ne prend alors qu’une partie entière. Problème résolu
bash ne vous donnera pas un résultat correct de 3/2 car il ne fait pas de maths flottants. vous pouvez utiliser des outils comme awk
$ awk 'BEGIN { rounded = sprintf("%.0f", 3/2); print rounded }'
2
ou bc
$ printf "%.0f" $(echo "scale=2;3/2" | bc)
2
Si vous avez une division entière de nombres positifs qui arrondit à zéro, vous pouvez ajouter un moins que le diviseur au dividende pour le arrondir.
C'est-à-dire, remplacez X / Y
par (X + Y - 1) / Y
.
Preuve:
Cas 1: X = k * Y
(X est un multiple entier de Y): Dans ce cas, nous avons (k * Y + Y - 1) / Y
, qui se divise en (k * Y) / Y + (Y - 1) / Y
. La partie (Y - 1)/Y
est arrondie à zéro et il nous reste un quotient de k
. C'est exactement ce que nous voulons: lorsque les entrées sont divisibles, nous voulons que le calcul ajusté produise toujours le quotient exact correct.
Cas 2: X = k * Y + m
où 0 < m < Y
(X n'est pas un multiple de Y). Dans ce cas, nous avons un numérateur de k * Y + m + Y - 1
ou k * Y + Y + m - 1
et nous pouvons écrire la division en tant que (k * Y)/Y + Y/Y + (m - 1)/Y
. Depuis 0 < m < Y
, 0 <= m - 1 < Y - 1
et ainsi de suite, le dernier terme (m - 1)/Y
passe à zéro. Il nous reste (k * Y)/Y + Y/Y
qui fonctionne en k + 1
. Cela montre que le comportement est arrondi. Si nous avons une X
qui est un k
multiple de Y
, si nous ajoutons seulement 1, la division arrondit à k + 1
.
Mais cet arrondi est extrêmement opposé; toutes les divisions inexactes s'éloignent de zéro. Que diriez-vous de quelque chose entre les deux?
Cela peut être réalisé en "amorçant" le numérateur avec Y/2
. Au lieu de X/Y
, calculez (X+Y/2)/Y
. Au lieu de la preuve, allons empiriquement sur celui-ci:
$ 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
Chaque fois que le diviseur est un nombre pair positif, si le numérateur est égal à la moitié de ce nombre, il arrondit et arrondit s'il est inférieur à un.
Par exemple, round 6 12
passe à 1
, de même que toutes les valeurs égales à 6
, modulo 12
, comme 18
(qui passe à 2) et ainsi de suite. round 5 12
descend à 0
.
Pour les nombres impairs, le comportement est correct. Aucun des nombres rationnels exacts n'est à mi-chemin entre deux multiples consécutifs. Par exemple, avec un dénominateur de 11
, nous avons 5/11 < 5.5/11 (exact middle) < 6/11
; et round 5 11
est arrondi, alors que round 6 11
est arrondi.
Pour arrondir, vous pouvez utiliser le module.
La deuxième partie de l'équation sera ajoutée à True s'il reste un reste. (Vrai = 1; Faux = 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
ex: 100/3
answer=$(((100 / 3) + (100 % 3 > 0)))
echo $answer
34
Étant donné une valeur en virgule flottante, nous pouvons l'arrondir trivialement avec printf:
# round $1 to $2 decimal places
round() {
printf "%.2f" "$1"
}
Ensuite,
# 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
Ou, pour utiliser la demande initiale:
$ echo "3/2, rounded to the nearest integer, is $(round $(math "3/2") 0)"
3/2, rounded to the nearest integer, is 2
Une autre solution consiste à effectuer la division dans une commande python. Par exemple:
$ numerator=90
$ denominator=7
$ python -c "print (round(${numerator}.0 / ${denominator}.0))"
Cela me semble moins archaïque que d'utiliser awk.
Si le séparateur décimal est une virgule (par exemple: LC_NUMERIC = fr_FR.UTF-8, voir ici ):
$ printf "%.0f" $(echo "scale=2;3/2" | bc)
bash: printf: 1.50: nombre non valable
0
La substitution est nécessaire pour la solution ghostdog74:
$ printf "%.0f" $(echo "scale=2;3/2" | bc | sed 's/[.]/,/')
2
ou
$ printf "%.0f" $(echo "scale=2;3/2" | bc | tr '.' ',')
2
Je pense que cela devrait être suffisant.
$ echo "3/2" | bc
La suite a fonctionné pour moi.
#!/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