Страницы

Поиск по вопросам

вторник, 21 мая 2019 г.

Почему невозможно сделать побитовое смещение для вещественных чисел?

Даже для целых вещественных не получается, почему так?


Ответ

c11 стандарт говорит (§6.5.7/2):
Each of the operands shall have integer type.
то есть сдвиг определён только для целых типов.
Причём даже для целых, операция определена только для некоторых значений. К примеру, i << n не определено, если i < 0 или i > 0 имеет тип со знаком и результат i·2n вне диапазона типа i (§6.5.7/4). В переносимых случаях, сдвиг это умножение/деление на 2

0b01000'0001 << 1 : 129 << 1 == 0b1000'00010 : == 258
0b01000'0001 >> 1 : 129 >> 1 == 0b001000'000 : == 64
Можно себе представить, что результат в этом случае получается буквальным сдвигом битов в двоичном представлении числа:

Действительные числа представлены в Си как числа с плавающей точкой. Можно думать о них как о числах, записанных в научной нотации: 1,234·105. Более формально (§5.2.4.2.2/2):

p ___ ╲ e ╲ -k x = b ⋅s⋅ ╱ b ⋅fₖ ╱ ‾‾‾ k = 1
x — само число s — знак (±1) b — основание системы счисления (к примеру, 2) e — показатель степени (экспонента) p — точность (число значащих цифр) fk — значащие цифры (0,1 для двоичной системы)
Пример: x = 106⋅(+1)⋅(1⋅10-1+2⋅10-2+3⋅10-3+4⋅10-4) = 1,234·105
На практике представление ещё ограничено IEEE 754 стандартом. Чтобы освоиться, можно посмотреть на пример миниформата числа, использующего 8 бит: SEEEEMMM (1.4.3.-2). В этом формате 128.0 и 256.0 будут представлены как:
0 0101 000 = +1.000×25-(-2) = 128.0 0 0110 000 = +1.000×26-(-2) = 256.0
так как 1012 = 510 и 1102 = 610 (смещение экспоненты -2).
Не хватает точности, чтобы 129.0 и 258.0 представить, поэтому используются ближайшие представимые числа: 128.0 и 256.0. Умножение на два — это просто увеличение экспоненты на один для нормальных чисел.
Сдвиг непосредственно битового представления числа особого смысла здесь не имеет:
129.0 << 1 = 0 0101 000 << 1 = 0 1010 000 = +1.000×210-(-2) = 4096.0 258.0 >> 1 = 0 0110 000 >> 1 = 0 0011 000 = +1.000×23-(-2) = 32.0
Даже для положительных целых чисел (все явные биты мантиссы нулевые), представленных в таком формате, сдвиг отличается от умножения/деления на 2. Ещё пример:
0 1000 001 = +1.125×28-(-2) = 1152.0 0 1000 001 >> 1 = 0 0100 000 = +1.000×24-(-2) = 64.0 0 1000 001 << 1 = 1 0000 010 = -0.250×21-(-2) = -2.0
Здесь буквальный сдвиг битов представления меняет и знак и дробную часть. Вводить такую операцию не слишком полезно.
Вот конвертор из битового представления во float и обратно.

Комментариев нет:

Отправить комментарий