Целочисленное деление в awk - программирование
Подтвердить что ты не робот

Целочисленное деление в awk

Я хочу разделить два числа в awk, используя целочисленное деление, т.е. обрезая результат. Например

k = 3 / 2
print k

должен печатать 1

В соответствии с руководство,

Отдел; поскольку все числа в awk являются числами с плавающей запятой, результат не округляется до целого числа

Есть ли какое-либо обходное решение для получения целочисленного значения?

Причина в том, что я хочу получить средний элемент массива с целыми индексами [0 - num-1].

4b9b3361

Ответ 1

Используйте функцию int, чтобы получить целую часть результата, усеченную в направлении 0. Это приводит к получению ближайшего целого числа к результату, расположенному между результатом и 0. Например, int(3/2) равно 1, int(-3/2) -1.

Источник: Руководство AWK - числовые функции

Ответ 2

Безопасное и быстрое целочисленное деление awk можно выполнить с помощью:

q=(n-n%d)/d+(n<0)

Ответ 3

В простых случаях вы можете безопасно использовать 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 и арифметику с плавающей запятой 3. Единственный способ получить целые числа и целочисленную арифметику - использовать внешние инструменты, например. стандартная утилита expr:

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

Это действительно неудобно, долго, медленно, но безопасно и портативно.


1 В POSIX awk, усечение до нуля гарантируется только для положительных аргументов: int (x) - Возвращает аргумент, усеченный до целого. Усечение должно быть равным 0 при х > 0. GNU awk (gawk) использует усечение к нулю даже для отрицательных чисел: int (x) - возвращает ближайшего целого числа к x, расположенного между x и нулем и усеченного к нулю. Например, int (3) равно 3, int (3.9) равно 3, int (-3.9) - -3, а int (-3) также равно 3.
2 Числовые выражения задаются как float с двойной точностью в Выражения в awk в POSIX.
3 Вся арифметика должна следовать семантике арифметики с плавающей запятой, указанной в стандарте 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
    

Подробнее о том, как работают float: