Страницы

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

среда, 4 марта 2020 г.

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

#c


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


Ответы

Ответ 1



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 и обратно.

Ответ 2



Можно. Это называется "деление на два" и "умножение на два".

Ответ 3



Бинарное представление таких чисел отличается от бинарного представления целочисленных, поэтому здесь и результаты побитовых операций отличаются. Любое вещественное число представлено в виде 1.m * 2^e где m - мантисса, e - экспонента. Вот из этих e и m и состоит бинарное представление числа, только значение e еще сдвинуто на полдиапазона, чтобы автоматически учитывался знак экспоненты при арифметических операциях над ними. Побитовый сдвиг вещественного (как и целочисленного) - это умножение или деление на 2, поэтому побитовый сдвиг вещественного равнозначен приращению экспоненты, например, сдвиг влево: 1.m * 2^e * 2^1 = 1.m * 2^(e+1) Подробности можно узнать из стандарта IEE754

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

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