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 bash
especí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 $float
similares 1.2e9
o, .12
por 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 printf
implementaciones (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, printf
independientemente 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 %f
que 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 awk
ya que ya es un carácter especial en la sintaxis allí ( print 1,2
igual que print 1, 2
para 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 double
s 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 ksh93
aritmé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 zsh
pero 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