web-dev-qa-db-fra.com

Arrondir un nombre divisé dans Bash

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

43
Mint

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
68
Ben Voigt

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

29
Ashish

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
25
ghostdog74

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 + m0 < 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.

8
Kaz

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
4
sk8asd123

É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
4
N. Ingersoll

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.

2
Sean Staats

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
1
Q-D

Je pense que cela devrait être suffisant.

$ echo "3/2" | bc 
1
guest

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
0
xs2rashid