Очень странно, я обнаружил, что в awk большое целое число выглядит так, как будто оно имеет только 53 бита. Вот мой пример:
function bits2str(bits,data, mask)
{
if (bits == 0)
return "0"
mask = 1
for (; bits != 0; bits = rshift(bits, 1))
data = (and(bits, mask) ? "1" : "0") data
while ((length(data) % 8) != 0)
data = "0" data
return data
}
BEGIN{
print 32,"\tlshift 48:\t", lshift(32,48), "\t", bits2str(lshift(32,48))
print 429,"\tlshift 48:\t", lshift(429,48), "\t", bits2str(lshift(429,48))
}
и вывод:
32 lshift 48: 0 0
429 lshift 48: 3659174697238528 00001101000000000000000000000000000000000000000000000000
но в C ++ его вывод:
32 lshift 48: 9007199254740992
429 lshift 48: 120752765008871424
После сравнения двух выходных данных я обнаружил, что у awk только 53 бита,
а затем я исследовал исходный код gawk (начиная со строки 3021 в файле с именем builtin.c, gawk 4.1.1, http://ftp.gnu.org/gnu/gawk/), но я не нашел специальной операции над int.
Итак, что вызывает это? Почему это так?
В AWK все числа хранятся с плавающей запятой.
От Битовая функция:
Для всех этих функций сначала значение с плавающей запятой двойной точности преобразуется в самый широкий целочисленный тип C без знака, затем выполняется побитовая операция. Если результат не может быть представлен точно как двойная буква C, начальные ненулевые биты удаляются один за другим, пока он не может быть представлен точно. Результат затем конвертируется обратно в C двойной.
Предполагая, что IEEE-754 используется, double
s может представлять только целые числа до 253.
если вы используете gawk, вам нужно добавить -M
вариант для большого номера.
kent$ awk 'BEGIN{print lshift(32,48)}'
0
kent$ awk -M 'BEGIN{print lshift(32,48)}'
9007199254740992