golpetazo
En bash, eso es probablemente tan bueno como se pone. Eso usa un caparazón incorporado. Si necesita el resultado en una variable, puede usar la sustitución de comandos o la bashespecífica (aunque ahora también es compatible con zsh):
printf -v int %.0f "$float"
Podrías hacerlo:
float=1.23
int=${float%.*}
Pero eso eliminaría la parte fraccionaria en lugar de darle el número entero más cercano y eso no funcionaría para valores $floatsimilares 1.2e9o, .12por ejemplo.
También tenga en cuenta las posibles limitaciones debido a la representación interna de flotadores:
$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560
Sí obtienes un número entero, pero es probable que no puedas usar ese número entero en ninguna parte.
Además, como señaló @BinaryZebra, en varias printfimplementaciones (bash, ksh93, yash, no GNU, zsh, dash), se ve afectado por la configuración regional (el separador decimal que puede ser .o ,).
Por lo tanto, si sus flotantes siempre se expresan con el punto como separador decimal y desea que se trate como tal, printfindependientemente de la configuración regional del usuario que invoca su secuencia de comandos, deberá corregir la configuración regional en C:
LC_ALL=C printf '%.0f' "$float"
Con yash, también puedes hacer:
printf '%.0f' "$(($float))"
(vea abajo).
POSIX
printf "%.0f\n" 1.1
no es POSIX ya %fque no es necesario que sea compatible con POSIX.
POSIXY, puedes hacer:
f2i() {
awk 'BEGIN{for (i=1; i<ARGC;i++)
printf "%.0f\n", ARGV[i]}' "$@"
}
Ese no se ve afectado por la configuración regional (la coma no puede ser un separador decimal awkya que ya es un carácter especial en la sintaxis allí ( print 1,2igual que print 1, 2para pasar dos argumentos print)
zsh
En zsh(que admite aritmética de coma flotante (el separador decimal es siempre el punto)), tiene la rint()función matemática para darle el entero más cercano como flotante (como en C) y int()para darle un entero desde un flotante (como en awk). Entonces puedes hacer:
$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123
O:
$ integer i=$((rint(5.678e2)))
$ echo $i
568
Sin embargo, tenga en cuenta que si bien doubles puede representar números muy grandes, los enteros son mucho más limitados.
$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808
ksh93
ksh93 fue el primer shell similar a Bourne que admitió la aritmética de coma flotante. ksh93 optimiza la sustitución de comandos al no usar una tubería o bifurcación cuando los comandos son solo comandos incorporados. Entonces
i=$(printf '%.0f' "$f")
no se bifurca O mejor:
i=${ printf '%.0f' "$f"; }
que tampoco se bifurca pero tampoco se toma la molestia de crear un entorno falso de subshell.
También puedes hacer:
i=$((rint(f)))
Pero cuidado con:
$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19
También puedes hacer:
integer i=$((rint(f)))
Pero como por zsh:
$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808
Tenga en cuenta que la ksh93aritmética de coma flotante respeta la configuración del separador decimal en la configuración regional (aunque de ,lo contrario es un operador matemático ( $((1,2))sería 6/5 en una configuración regional en francés / alemán ... y lo mismo que $((1, 2)), eso es 2 en una configuración regional en inglés) .
yash
yash también admite aritmética de coma flotante, pero no tiene funciones matemáticas como ksh93/ zsh's rint(). Sin embargo, puede convertir un número a entero utilizando el binario o el operador (también funciona zshpero no en ksh93). Sin embargo, tenga en cuenta que trunca la parte decimal, no le da el entero más cercano:
$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19))"
-9223372036854775808
yash respeta el separador decimal de la configuración regional en la salida, pero no para las constantes literales de coma flotante en sus expresiones aritméticas, lo que puede causar sorpresas:
$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator
Es bueno de alguna manera, ya que puede usar constantes de punto flotante en sus scripts que usan el punto y no tiene que preocuparse de que deje de funcionar en otras configuraciones regionales, pero aún así pueda manejar los números expresados por el usuario durante tanto tiempo. como recuerdas hacer:
var=$((10.3)) # and not var=10.3
... "$((a + 0.1))" # and not "$(($a + 0.1))".
printf '%.0f\n' "$((10.3))" # and not printf '%.0f\n' 10.3