frapper
Dans bash
, c'est probablement aussi bon que cela. Cela utilise un shell intégré. Si vous avez besoin du résultat dans une variable, vous pouvez utiliser la substitution de commande, ou la commande bash
spécifique (bien que désormais également prise en charge par zsh
):
printf -v int %.0f "$float"
Vous pourriez faire:
float=1.23
int=${float%.*}
Mais cela supprimerait la partie décimale au lieu de vous donner l'entier le plus proche et cela ne fonctionnerait pas pour des valeurs de $float
type similaire 1.2e9
ou .12
par exemple.
Notez également les limitations possibles dues à la représentation interne des floats:
$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560
Vous obtenez un entier, mais il est probable que vous ne pourrez utiliser cet entier nulle part.
De plus, comme l'a noté @BinaryZebra, dans plusieurs printf
implémentations (bash, ksh93, yash, et non GNU, zsh, dash), il est affecté par les paramètres régionaux (le séparateur décimal qui peut être .
ou ,
).
Ainsi, si vos flottants sont toujours exprimés avec le point comme séparateur décimal et que vous souhaitez le traiter comme tel printf
quel que soit le paramètre régional de l'utilisateur qui appelle votre script, vous devez le définir en C:
LC_ALL=C printf '%.0f' "$float"
Avec yash
, vous pouvez aussi faire:
printf '%.0f' "$(($float))"
(voir ci-dessous).
POSIX
printf "%.0f\n" 1.1
ne POSIX %f
n'a pas à être pris en charge par POSIX.
POSIXly, vous pouvez faire:
f2i() {
awk 'BEGIN{for (i=1; i<ARGC;i++)
printf "%.0f\n", ARGV[i]}' "$@"
}
Celui-ci n'est pas affecté par les paramètres régionaux (la virgule ne peut pas être un séparateur décimal, awk
car il s'agit déjà d'un caractère spécial dans la syntaxe ( print 1,2
identique print 1, 2
à celle utilisée pour passer deux arguments print
).
zsh
Dans zsh
(qui prend en charge l’arithmétique en virgule flottante (le séparateur décimal est toujours la période)), vous avez la rint()
fonction mathématique qui vous donne l’entier le plus proche sous forme de float (comme dans C
) et int()
un entier à partir de float (comme dans awk
). Alors tu peux faire:
$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123
Ou:
$ integer i=$((rint(5.678e2)))
$ echo $i
568
Cependant, notez que double
s peut représenter de très grands nombres, les nombres entiers sont beaucoup plus limités.
$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808
ksh93
ksh93 était le premier shell de type Bourne à supporter l'arithmétique en virgule flottante. ksh93 optimise la substitution de commande en n'utilisant pas de canal ou en forçant lorsque les commandes ne sont que des commandes intégrées. Alors
i=$(printf '%.0f' "$f")
ne fourche pas. Ou même mieux:
i=${ printf '%.0f' "$f"; }
ce qui ne va pas non plus, mais ne va pas non plus tout le problème de la création d’un faux environnement de sous-shell.
Vous pouvez aussi faire:
i=$((rint(f)))
Mais méfiez-vous de:
$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19
Vous pouvez aussi faire:
integer i=$((rint(f)))
Mais comme pour zsh
:
$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808
Attention, l' ksh93
arithmétique en virgule flottante respecte le paramètre de séparateur décimal défini dans l'environnement local (même s'il ,
s'agit par ailleurs d'un opérateur mathématique ( $((1,2))
serait 6/5 dans un environnement français / allemand ... et identique $((1, 2))
, 2 dans un environnement anglais) .
yash
Yash prend également en charge l' arithmétique en virgule flottante , mais ne dispose pas de fonctions mathématiques comme ksh93
/ zsh
s » rint()
. Vous pouvez toutefois convertir un nombre en entier en utilisant le binaire ou l' opérateur par exemple (fonctionne également dans zsh
mais pas dans ksh93
). Notez cependant que cela tronque la partie décimale, il ne vous donne pas l'entier le plus proche:
$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19))"
-9223372036854775808
yash
respecte le séparateur décimal des paramètres régionaux en sortie, mais pas les constantes littérales à virgule flottante dans ses expressions arithmétiques, ce qui peut entraîner des surprises:
$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator
En un sens, vous pouvez utiliser des constantes à virgule flottante dans vos scripts qui utilisent la période et ne pas avoir à craindre que celle-ci ne fonctionne plus dans d'autres paramètres régionaux, tout en conservant la capacité de traiter les nombres tels qu'exprimés par l'utilisateur aussi longtemps. comme tu te souviens de le faire:
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