Даже для целых вещественных не получается, почему так?
Ответ
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 и обратно.
Комментариев нет:
Отправить комментарий