Bash: Float a Entero

¿Es esta la forma correcta de hacer flotar a un integer en bash, o hay algún otro método?

flotToint() { printf "%.0f\n" "$@" } 

bash

En bash , eso es probablemente tan bueno como se pone. Eso usa un shell incorporado. Si necesita el resultado en una variable, puede usar la sustitución de command o el bash específico:

 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 integer más cercano y eso no funcionaría para valores de $float como 1.2e9 o .12 por ejemplo.

También tenga en count las posibles limitaciones debido a la representación interna de flotadores:

 $ printf '%.0f\n' 1e50 100000000000000007629769841091887003294964970946560 

Obtienes un integer, pero es probable que no puedas usar ese integer en ninguna parte.

Además, como señala @BinaryZebra, en varias implementaciones de printf (bash, ksh93, yash, no GNU, zsh, dash), se ve afectado por la configuration regional (el separador decimal que puede ser .o , ).

Por lo tanto, si sus flotantes siempre se expresan con el período como el separador decimal y desea que se trate como tal mediante printf independientemente de la configuration regional del usuario que invoca su secuencia de commands, deberá corregir la configuration regional en C:

 LC_ALL=C printf '%.0f' "$float" 

Con yash , también puedes hacer:

 printf '%.0f' "$(($float))" 

para que el contenido de $float se convierta al formatting en la configuration regional actual.

POSIX

 printf "%.0f\n" 1.1 

no es POSIX, ya que %f no es necesario para ser compatible con POSIX.

POSIXly, puedes hacer:

 f2i() { awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%.0f\n", ARGV[i]}' "$@" } 

Ese no se ve afectado por la configuration regional (la coma no puede ser un separador decimal en awk ya que ya es un carácter especial en la syntax allí ( print 1,2 , igual que print 1, 2 para pasar dos arguments para print )

zsh

En zsh (que admite la aritmética de coma flotante (el separador decimal es siempre el punto)), tiene la function matemática rint() para darle el integer más cercano como un flotante (como en C ) e int() para darle un número integer de un flotador (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 count que, si bien las double s pueden representar numbers muy grandes, los integers son mucho más limitados.

 $ printf '%.0f\n' 1e123 999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376 $ echo $((int(1e123))) -9223372036854775808 

ksh93

ksh93 fue la primera shell tipo Bourne que admite la aritmética de coma flotante. ksh93 optimiza la sustitución de commands al no usar una tubería o bifurcación cuando los commands son solo commands integrados. Asi que

 i=$(printf '%.0f' "$f") 

no tenedor.

También puedes hacer:

 i=$((rint(f))) 

Pero ten cuidado con:

 $ echo "$((rint(1e18)))" 1000000000000000000 $ echo "$((rint(1e19)))" 1e+19 

También podrías hacer:

 integer i=$((rint(f))) 

Pero como para zsh :

 $ integer i=1e18 $ echo "$i" 1000000000000000000 $ integer i=1e19 $ echo "$i" -9223372036854775808 

Tenga en count que la aritmética de punto flotante ksh93 la configuration del separador decimal en la configuration regional (aunque , lo contrario, un operador matemático ( $((1,2)) sería 6/5 en una configuration regional francés / alemán, y lo mismo como $((1, 2)) , eso es 2 en una configuration regional en inglés).

yash

yash también admite la aritmética de coma flotante, pero no tiene funciones matemáticas como ksh93 rint() ksh93 / zsh . Sin embargo, puede convertir un número a integer usando el operador binary u operador (también funciona en zsh pero no en ksh93 ). Sin embargo, tenga en count que trunca la parte decimal, no le da el integer más cercano:

 $ echo "$((0.237e2 | 0))" 23 $ echo "$((1e19))" -9223372036854775808 

yash respeta el separador decimal de la configuration regional en la salida, pero no las constantes literales de coma flotante en sus expresiones aritméticas, que pueden 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 porque puedes usar constantes de coma flotante en tus scripts que usan el período y no tener que preocuparte de que deje de funcionar en otras configuraciones regionales, pero aún así ser capaz de manejar los numbers expresados ​​por el usuario siempre y cuando como restrings 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 

bc – Un lenguaje de calculadora de precisión arbitraria

int (float) debería verse así:

 $ echo "$float/1" | bc 1234 

Para networkingondear mejor, utiliza esto:

 $ echo "($float+0.5)/1" | bc 

Ejemplo:

 $ float=1.49 $ echo "($float+0.5)/1" | bc 1 $ float=1.50 $ echo "($float+0.5)/1" | bc 2 

instale el progtwig de pitido con:

 aptitude install beep or apt-get install beep 

y escucha la function seno de esta manera:

1a. define la function en bash:

 $ function sinus () { a=$1; b=$2; n=$3; f=$4; d=$(echo "scale=$f; ($b-$a)/$n"|bc); for m in $(seq 0 $n); do x=$(echo "scale=$f;$a+$m*$d"|bc); y=$(echo "scale=$f;s($x)"|bc -l); #printf "%0.${f}f\t" "$x"; #printf "%0.${f}f\n" "$y"; z=$(echo "scale=$f; 2300+2000*$y" | bc); beep -f "$z" -l 2 -d 0; done | column -t } 

2a. Llame a esta function de esta manera:

 $ sinus 1 20 300 4 

Nota : 'sinus abnf' significa escuchar el sonido del seno (en radianes) de aa b dividiendo el intervalo en n + 1 partes iguales usando f decimales. Hay más cosas de las necesarias en la function porque puede usarlas para trazar o cualquier otra cosa. También puede escribir leer abnf en lugar de las inicializaciones.

Además, es muy divertido, aplastando los ciclos en la function seno cada vez más hasta que el progtwig no lo soporte:

1b. definir:

 $ function sinus-inv () { a=$1; b=$2; n=$3; f=$4; d=$(echo "scale=$f; ($b-$a)/$n"|bc); for m in $(seq 1 $n); do x=$(echo "scale=$f;$a+$m*$d"|bc); y=$(echo "scale=$f;s(8000/($b-$x))"|bc -l); z=$(echo "scale=$f; 2300+2000*$y" | bc); beep -f "$z" -l 1 -d 0; done; } 

2b. Ejemplo de llamada:

 $ sinus-inv 1 100 1000 8 

La respuesta anterior enviada fue casi correcta: "Podría hacer:

 float=1.23 int=${float%.*} 

Pero eso eliminaría la parte fraccionaria en lugar de darle el integer más cercano y eso no funcionaría para valores de $ float como 1.2e9 o .12 por ejemplo … "

Simplemente use ${float%%.*} .

 echo ${float%%.*} 1 

Un hacky muy simple es

 function float_to_int() { echo $1 | cut -d. -f1 # or use -d, if decimals separator is , } 

Muestra de salida

 $ float_to_int 32.333 32 $ float_to_int 32 32