Je veux diviser deux nombres en awk
, en utilisant une division entière, c'est-à-dire en tronquant le résultat. Par exemple
k = 3 / 2
print k
devrait imprimer 1
Selon le manuel ,
Division; parce que tous les nombres dans awk sont des nombres à virgule flottante, le résultat est non arrondi à un entier
Existe-t-il une solution de contournement pour obtenir une valeur entière?
La raison en est que je veux obtenir le élément central d'un tableau avec entier index [0 à num-1].
Utilisez la fonction int
pour obtenir la partie entière du résultat, tronquée vers 0. Cela produit l'entier le plus proche du résultat, situé entre le résultat et 0. Par exemple, int(3/2)
est 1 , int(-3/2)
est -1.
Dans les cas simples, vous pouvez utiliser en toute sécurité int()
qui tronque vers zéro1:
awk 'BEGIN { print int(3 / 2) }' # prints 1
gawk 'BEGIN { print int(-3 / 2) }' # prints -1; not guaranteed in POSIX awk
Gardez à l'esprit que awk utilise toujours des nombres à virgule flottante double précision2 et arithmétique à virgule flottante3, bien que. La seule façon d'obtenir des nombres entiers et de l'arithmétique entière est d'utiliser des outils externes, par ex. l'utilitaire standard expr
:
awk 'BEGIN { "expr 3 / 2" | getline result; print result; }' # prints 1
C'est vraiment awk ward, long, lent,… mais sûr et portable.
1 Dans POSIX awk , la troncature à zéro n'est garantie que pour les arguments positifs: int (x) - Retourne l'argument tronqué à un entier. La troncature doit être vers 0 lorsque x> 0. GNU awk (gawk) utilise la troncature vers zéro même pour les nombres négatifs: int (x) - Renvoie l'entier le plus proche à x, situé entre x et zéro et tronqué vers zéro. Par exemple, int (3) est 3, int (3.9) est 3, int (-3.9) est -3 et int (-3) est également -3.
2 Les expressions numériques sont spécifiées comme des flottants à double précision dans Expressions dans awk dans POSIX.
3 Toute l'arithmétique doit suivre la sémantique de l'arithmétique à virgule flottante telle que spécifiée par la norme ISO C (voir Concepts dérivés de la norme ISO C ). - awk POSIX: fonctions arithmétiques
Si vous choisissez d'utiliser des flotteurs, vous devez connaître leurs bizarreries et être prêt à les repérer et à éviter les bugs associés. Plusieurs exemples effrayants:
Numéros non représentables:
awk 'BEGIN { x = 0.875; y = 0.425; printf("%0.17g, %0.17g\n", x, y) }'
# prints 0.875, 0.42499999999999999
Erreurs d'arrondi accumulation:
awk 'BEGIN{s=0; for(i=1;i<=100000;i++)s+=0.3; printf("%.10f, %d\n",s,int(s))}'
# prints 29999.9999999506, 29999
Les erreurs d'arrondi ruinent les comparaisons:
awk 'BEGIN { print (0.1 + 12.2 == 12.3) }' # prints 0
La précision diminue avec l'amplitude, provoquant des boucles infinies:
awk 'BEGIN { for (i=10^16; i<10^16+5; i++) printf("%d\n", i) }'
# prints 10000000000000000 infinitely many times
En savoir plus sur le fonctionnement des flotteurs:
Balises de débordement de pile virgule flottante wiki
Article Wikipedia virgule flottante
arithmétique de précision arbitraire GNU awk - contient à la fois des informations sur l'implémentation spécifique et des connaissances générales
La division sûre et rapide des entiers awk peut être effectuée avec:
q=(n-n%d)/d+(n<0)