#c #linux #awk #bit-manipulation
#c #linux #awk #манипулирование битами
Вопрос:
Очень странно, я обнаружил, что в 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.
Итак, что вызывает это? Почему это так?
Ответ №1:
В AWK все числа хранятся с плавающей запятой.
Для всех этих функций сначала значение с плавающей запятой двойной точности преобразуется в самый широкий целочисленный тип C без знака, затем выполняется побитовая операция. Если результат не может быть представлен точно как C double , начальные ненулевые биты удаляются один за другим, пока он не будет представлен точно. Затем результат преобразуется обратно в C double .
Предполагая, что используется IEEE-754, double
s может представлять только целые числа до 2 53.
Ответ №2:
если вы используете gawk, вам нужно добавить -M
опцию для большого числа.
kent$ awk 'BEGIN{print lshift(32,48)}'
0
kent$ awk -M 'BEGIN{print lshift(32,48)}'
9007199254740992
Комментарии:
1. Нет, это не работает. У моего gawk / awk нет этой опции. Моя версия awk — GNU Awk 3.1.5, как насчет вас?
2. В своем вопросе вы упомянули, что проверили коды gawk 4.1.1. итак, я тестировал с 4.1.1. Если вы работаете над 3.1.5, почему вы проверили коды 4.1.1? @xingwudao
3. Ага, извините, это такая глупая попытка для меня! Я установлю 4.1.1 на свой компьютер.
4. Спасибо за вашу помощь!