web-dev-qa-db-ja.com

awkの整数除算

整数除算を使用して、つまり結果を切り捨てて、awkの2つの数値を除算したいと思います。例えば

k = 3 / 2
print k

印刷する必要があります1

マニュアル によると、

分割; awkのすべての数値は浮動小数点数であるため、結果は整数に丸められません

整数値を取得するための回避策はありますか?

その理由は、integerインデックス[0 to num-1]を持つ配列の中間要素を取得したいためです。

21
user000001

int関数を使用して、結果の整数部を0に切り捨てます。これにより、結果と0の間にある、結果に最も近い整数が生成されます。たとえば、int(3/2)は1です。 、int(-3/2)は-1です。

出典: AWKマニュアル-数値関数

36
Gilles Quenot

単純なケースでは、ゼロに向かって切り捨てるint()を安全に使用できます1

awk 'BEGIN { print int(3 / 2) }'    # prints 1
gawk 'BEGIN { print int(-3 / 2) }'  # prints -1; not guaranteed in POSIX awk

Awkは常に倍精度浮動小数点数を使用することに注意してください2 および浮動小数点演算、しかし。整数と整数演算を取得できる唯一の方法は、外部ツールを使用することです。標準のexprユーティリティ:

awk 'BEGIN { "expr 3 / 2" | getline result; print result; }'    # prints 1

これは本当にawkward、long、slow、…ですが、安全で移植可能です。


1POSIX awk では、ゼロへの切り捨ては正の引数に対してのみ保証されます:int(x)—整数に切り捨てられた引数を返します。 GNU awk (gawk)は、負の数でもゼロに向かって切り捨てを使用します:int(x)—を返しますxとゼロの間に位置し、ゼロに向かって切り捨てられた、xに最も近い整数。たとえば、int(3)は3、int(3.9)は3、int(-3.9)は-3、int(-3)も-3です。
2 数値式は、POSIXの Expressions in awk で倍精度浮動小数点数として指定されます。
すべての演算は、ISO C標準で指定されている浮動小数点演算のセマンティクスに従います( ISO C標準から派生した概念 を参照)。—- POSIX awk:算術関数


フロートの使用を選択する場合は、フロートの癖を理解し、フロートを見つけて関連するバグを回避する準備をする必要があります。いくつかの恐ろしい例:

  • 表現できない数:

    awk 'BEGIN { x = 0.875; y = 0.425; printf("%0.17g, %0.17g\n", x, y) }'
    # prints 0.875, 0.42499999999999999
    
  • 丸め誤差 累積:

    awk 'BEGIN{s=0; for(i=1;i<=100000;i++)s+=0.3; printf("%.10f, %d\n",s,int(s))}'
    # prints 29999.9999999506, 29999
    
  • 丸め誤差は比較を台無しにします:

    awk 'BEGIN { print (0.1 + 12.2 == 12.3) }'    # prints 0
    
  • 精度は大きさとともに減少し、無限ループを引き起こします:

    awk 'BEGIN { for (i=10^16; i<10^16+5; i++) printf("%d\n", i) }'
    # prints 10000000000000000 infinitely many times
    

フロートがどのように機能するかについてもっと読む:

  1. スタックオーバーフロータグ floating-point wiki

  2. ウィキペディアの記事 浮動小数点

  3. GNU awk任意精度演算 –特定の実装に関する情報と一般的な知識の両方が含まれます

8
Palec

安全で迅速なawk整数除算は、次の方法で実行できます。

q=(n-n%d)/d+(n<0)
7
Marijan Unetić