Evite bucles en conchas.
Si quieres hacer aritmética, usa awk
o bc
:
awk '
BEGIN{
for (i = 4.00; i < 5.42; i+ = 0.02)
print i
}'
O
bc << EOF
for (i = 4.00; i < 5.42; i += 0.02) i
EOF
Tenga en cuenta que awk
(al contrario de bc
) funciona con la double
representación de números de coma flotante de sus procesadores (probablemente tipo IEEE 754 ). Como resultado, dado que esos números son aproximaciones binarias de esos números decimales, puede tener algunas sorpresas:
$ gawk 'BEGIN{for (i=0; i<=0.3; i+=0.1) print i}'
0
0.1
0.2
Si agrega un OFMT="%.17g"
puede ver el motivo de la falta 0.3
:
$ gawk 'BEGIN{OFMT="%.17g"; for (i=0; i<=0.5; i+=0.1) print i}'
0
0.10000000000000001
0.20000000000000001
0.30000000000000004
0.40000000000000002
0.5
bc
tiene una precisión arbitraria, por lo que no tiene este tipo de problema.
Tenga en cuenta que, de manera predeterminada (a menos que modifique el formato de salida OFMT
o use printf
especificaciones de formato explícito), se awk
usa %.6g
para mostrar números de coma flotante, por lo que cambiaría a 1e6 y superior para números de coma flotante superiores a 1,000,000 y truncaría la parte fraccionaria para números altos (100000.02 se mostrará como 100000).
Si realmente necesita usar un bucle cáscara, porque, por ejemplo, desea ejecutar comandos específicos para cada iteración de este bucle, o bien utilizar un depósito de flotación apoyo aritmética de punto como zsh
, yash
o ksh93
o generar la lista de valores con un comando que el anterior (o seq
si está disponible) y repita su salida.
Me gusta:
unset -v IFS # configure split+glob for default word splitting
for i in $(seq 4 0.02 5.42); do
something with "$i"
done
O:
seq 4 0.02 5.42 | while IFS= read i; do
something with "$i"
done
a menos que supere los límites de los números de coma flotante de su procesador, seq
maneja los errores incurridos por aproximaciones de coma flotante con más gracia que la awk
versión anterior.
Si no tiene seq
(un comando GNU), puede hacer uno más confiable como una función como:
seq() { # args: first increment last
bc << EOF
for (i = $1; i <= $3; i += $2) i
EOF
}
Eso funcionaría mejor para cosas como seq 100000000001 0.000000001 100000000001.000000005
. Sin embargo, tenga en cuenta que tener números con una precisión arbitrariamente alta no ayudará mucho si vamos a pasarlos a comandos que no los admiten.