2010-03-07 65 views
35

¿Cómo voy a redondear el resultado de dos números divididos, por ejemploRedondear un número dividido en Bash

3/2 

Como cuando lo haga

testOne=$((3/2)) 

$ TESTONE contiene "1" cuando debería haber redondeado a "2" como la respuesta de 3/2 = 1,5

+0

Esencialmente un paquete de actualización del SO 2.394.988 (http://stackoverflow.com/questions/2394988) - el mismo cartel. –

+0

De acuerdo, es muy similar, pero yo no lo llamaría un DUP, pero siéntanse libres de cerrarlo ahora, ya que de todos modos he recibido mi respuesta, ¡gracias ghostdog! – Mint

+4

de acuerdo! Las dos preguntas no son lo mismo. Uno está pidiendo techo. Este pide un redondeo que puede redondearse hacia arriba o hacia abajo. – shparekh

Respuesta

57

Para hacer redondeo en la aritmética de truncamiento, simplemente agregue (denom-1) al numerador.

ejemplo, redondeando hacia abajo:

N/2 
M/5 
K/16 

ejemplo, redondeando:

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

Para hacer todo el año a más cercano, añadir (denom/2) al numerador (mitades van redondeando hacia arriba):

(N+1)/2 
(M+2)/5 
(K+8)/16 
+0

¿Puedes explicar esto un poco más? ¿Cuál es el significado de uno? Y realmente no entiendo lo que están haciendo todos estos corchetes y letras ... Siento que debería saber ya que no ha habido otras respuestas y 5+ ups – Mint

+9

@Mint: muestra una respuesta general usando notación algebraica. Usando tu ejemplo de Bash, se vería así: 'testOne = $ (((3 + (2 - 1)/2))'. Incluso más generalmente, pero en la sintaxis de Bash, sería algo como 'answer = $ ((($ numerador + ($ denominador - 1)/$ denomonador)). También puede hacerlo de esta manera, lo que elimina todos los signos de dólar y permite más libertad con espacios (como alrededor del signo igual): '((respuesta = (numerador + (denominador - 1)/denominador)) ' –

+2

@Dennis: correcto, excepto que sus paréntesis están desequilibrados. –

21

fiesta no le dará resultado correcto de 3/2, ya que no hace las matemáticas pt flotantes. puede utilizar herramientas como awk

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

o BC

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

awk 'BEGIN {redondeado = sprintf ("%. 0f ", 1/2); print rounded} 'devuelve 0 y no 1. –

+2

Debe tener en cuenta que esto hace un redondeo imparcial. –

+0

Me gusta esta, ya que es más fácil de leer (las soluciones matemáticas son buenas pero no legibles), y no necesito precisión sobre el redondeo de 0.5. Tenga en cuenta que 'awk 'BEGIN {redondeado = sprintf ("%. 0f ", 1.000001/2); print rounded} '' devuelve 1 –

2

Otra solución es hacer la división dentro de un comando de pitón. Por ejemplo:

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

Me parece menos arcaico que usar awk.

+0

adenda: al redondear hacia abajo también puede usar la división del piso: imprimir $ {numerador} // $ {denominador} – Jarno

18

buena solución es conseguir más cercano Redondo es

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

lógica es simple si el valor de var decimal es inferior a 0,5 el valor más cercano a continuación, tomada es un valor entero. Bueno, si el valor decimal es mayor que .5, entonces se agrega el siguiente valor entero y como awk solo toma parte entera. Problema resuelto

+1

Solución muy simple y potente. ¡Estupendo! – Sigur

+0

Fue muy útil mientras estaba convirtiendo el uso de memoria de KB a MB ya que no me importa mucho la parte decimal – ashah

1

creo que esto debería ser suficiente.

$ echo "3/2" | bc 
+2

Eso funciona para su ejemplo, sin embargo 'echo" 2.5 * 3 "| bc 'da' 7.5' – mhwombat

6

Si usted tiene una división entera de números positivos que se redondea hacia cero, a continuación, puede agregar una unidad menor que el divisor al dividendo para que sea redondear al alza.

Es decir, reemplace X/Y con (X + Y - 1)/Y.

Prueba:

  • Caso 1: X = k * Y (X es un número entero múltiplo de Y): En este caso, tenemos (k * Y + Y - 1)/Y, que se divide en (k * Y)/Y + (Y - 1)/Y. La pieza (Y - 1)/Y redondea a cero, y nos queda un cociente de k. Esto es exactamente lo que queremos: cuando las entradas son divisibles, queremos que el cálculo ajustado siga produciendo el cociente exacto correcto.

  • Caso 2: X = k * Y + m donde 0 < m < Y (X no es un múltiplo de Y). En este caso, tenemos un numerador de k * Y + m + Y - 1, o k * Y + Y + m - 1, y podemos escribir la división como (k * Y)/Y + Y/Y + (m - 1)/Y. Desde 0 < m < Y, 0 <= m - 1 < Y - 1, por lo que el último término (m - 1)/Y pasa a cero. Nos queda (k * Y)/Y + Y/Y que funcionan hasta k + 1. Esto muestra que el comportamiento se redondea. Si tenemos un X que es un k múltiplo de Y, si le agregamos solo 1, la división redondea hasta k + 1.

Pero este redondeo es extremadamente opuesto; todas las divisiones inexactas se alejan de cero. ¿Qué tal algo intermedio?

Esto se puede lograr "imprimando" el numerador con Y/2. En lugar de X/Y, calcule (X+Y/2)/Y. En lugar de la prueba, vamos a ir empírica en este caso:

$ 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 

Siempre que el divisor es un par, número positivo, si el numerador es congruente con la mitad de ese número, se redondea hacia arriba, y redondea a la baja si se trata de uno menos que eso.

Por ejemplo, round 6 12 va a 1, al igual que todos los valores que son iguales a 6, módulo 12, como 18 (que va a 2) y así sucesivamente. round 5 12 baja a 0.

Para los números impares, el comportamiento es correcto. Ninguno de los números racionales exactos están a mitad de camino entre dos múltiplos consecutivos. Por ejemplo, con un denominador de 11 tenemos 5/11 < 5.5/11 (exact middle) < 6/11; y round 5 11 redondea hacia abajo, mientras que round 6 11 redondea hacia arriba.

1

Si el separador decimal es una coma (por ejemplo: LC_NUMERIC = fr_FR.UTF-8, ver here): se necesita

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

Sustitución para ghostdog74 solución:

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

o

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

Para redondear puede usar el módulo.

La segunda parte de la ecuación se agregará a True si hay un residuo.(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 

ex: 100/3

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

Dado un valor de coma flotante, podemos redondearlo trivialmente con printf:

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

Entonces,

# 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 

O, para usar la solicitud original:

$ echo "3/2, rounded to the nearest integer, is $(round $(math "3/2") 0)" 
3/2, rounded to the nearest integer, is 2 
+0

'printf"% .0f "" 0.5 "' imprime '0' en lugar del' 1' esperado, mientras que 'printf"% .0f "" 0.6 "' imprime '1' como se esperaba. –

Cuestiones relacionadas