bater
Em bash
, isso é provavelmente tão bom quanto ele ganha. Isso usa um shell embutido. Se você precisar do resultado em uma variável, poderá usar a substituição de comandos ou o bash
específico (embora agora também seja suportado por zsh
):
printf -v int %.0f "$float"
Você poderia fazer:
float=1.23
int=${float%.*}
Mas isso removeria a parte fracionária em vez de fornecer o número inteiro mais próximo e não funcionaria para valores $float
iguais 1.2e9
ou .12
por exemplo.
Observe também as possíveis limitações devido à representação interna dos carros alegóricos:
$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560
Você recebe um número inteiro, mas é provável que não possa usá-lo em nenhum lugar.
Além disso, como observado pelo @BinaryZebra, em várias printf
implementações (bash, ksh93, yash, não GNU, zsh, dash), ele é afetado pelo código do idioma (o separador decimal que pode ser .
ou ,
).
Portanto, se seus carros alegóricos são sempre expressos com o período como separador decimal e você deseja que ele seja tratado como tal, printf
independentemente do código do idioma do usuário que está invocando seu script, será necessário corrigir o código do idioma para C:
LC_ALL=C printf '%.0f' "$float"
Com yash
, você também pode fazer:
printf '%.0f' "$(($float))"
(ver abaixo).
POSIX
printf "%.0f\n" 1.1
não é POSIX, pois %f
não é necessário ter suporte do POSIX.
POSIXly, você pode fazer:
f2i() {
awk 'BEGIN{for (i=1; i<ARGC;i++)
printf "%.0f\n", ARGV[i]}' "$@"
}
Esse não é afetado pelo código do idioma (a vírgula não pode ser um separador decimal, awk
pois já existe um caractere especial na sintaxe (o print 1,2
mesmo que print 1, 2
passar dois argumentos para print
)
zsh
Em zsh
(que suporta aritmética de ponto flutuante (o separador decimal é sempre o período)), você tem a rint()
função matemática para fornecer o número inteiro mais próximo como ponto flutuante (como em C
) e int()
para fornecer um número inteiro a partir de um ponto flutuante (como em awk
). Então você pode fazer:
$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123
Ou:
$ integer i=$((rint(5.678e2)))
$ echo $i
568
No entanto, observe que, enquanto double
s pode representar números muito grandes, números inteiros são muito mais limitados.
$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808
ksh93
O ksh93 foi o primeiro shell tipo Bourne a suportar aritmética de ponto flutuante. O ksh93 otimiza a substituição de comandos, não usando um pipe ou bifurcação quando os comandos são apenas comandos internos. assim
i=$(printf '%.0f' "$f")
não bifurca. Ou melhor ainda:
i=${ printf '%.0f' "$f"; }
que não bifurca, mas também não dá todo o trabalho de criar um ambiente de subcamação falso.
Você também pode fazer:
i=$((rint(f)))
Mas cuidado com:
$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19
Você também pode fazer:
integer i=$((rint(f)))
Mas como para zsh
:
$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808
Cuidado com o fato de que a ksh93
aritmética de ponto flutuante honra a configuração do separador decimal no código do idioma (mesmo que ,
seja um operador matemático ( $((1,2))
seria 6/5 em um código de idioma francês / alemão ... e o mesmo $((1, 2))
que é 2 em um código de idioma em inglês) .
yash
O yash também suporta aritmética de ponto flutuante, mas não possui funções matemáticas como ksh93
/ zsh
's rint()
. Você pode converter um número em número inteiro usando o binário ou o operador, por exemplo (também funciona em, zsh
mas não em ksh93
). Observe, no entanto, que ele trunca a parte decimal, não fornece o número inteiro mais próximo:
$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19))"
-9223372036854775808
yash
honra o separador decimal da localidade na saída, mas não para as constantes literais de ponto flutuante em suas expressões aritméticas, o que pode causar surpresas:
$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator
É bom, de certa forma, que você possa usar constantes de ponto flutuante em seus scripts que usam o período e não tenha que se preocupar que ele pare de funcionar em outros locais, mas ainda assim seja capaz de lidar com os números expressos pelo usuário desde como você se lembra de fazer:
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