Я знаю с нормальными целыми числами, которые вы можете разделить на бит-сдвиг вправо. Мне интересно, есть ли простой способ сделать то же самое с числами, которые не являются целыми числами.
ldexp
, ldexpf
и ldexpl
делают это для удвоений, поплавков и длинных удвоений соответственно. В качестве альтернативы, если у вас есть определенная сила двух в виду (скажем, 4), лучше всего просто разделить обычный способ:
whatever / 4
Существует функция ldexp
(и братья и сестры), которая позволяет вам "умножать на две степени" (включая отрицательные), это не та же оптимизация, что и использование сдвигов для целых чисел. Для двух степеней все двойные значения являются "идеальными" для X и 1/X (потому что если X равно 2 n то 1/X = 2 -n оба из которых прекрасно сохраняются как число с плавающей запятой в IEEE-754 или любой другой двоичный формат с плавающей запятой), поэтому не будет никакого нечетного округления, что означает, что компилятор должен иметь возможность заменить деление на операцию умножения - в моих экспериментах это действительно так.
Для управления показателем значений с плавающей запятой, как правило, вредно для производительности по сравнению с "применять умножить на 1/X".
Функция ldexp
- это несколько десятков инструкций длиной в glibc, с несколькими ветвями и вызовом в коде. Очень маловероятно, что вы найдете какую-либо выгоду от вызова ldexp
, а также смутите людей, которые не знают, что x = ldexp(x, -1);
такая же, как x/= 2.0;
,
Просто используйте
double x = 7;
x *= 2;
x /= 2;
assert(x == 7.0);
или
double y = 5;
y = 2*x + 0.5*y;
assert(y == 16.5);
или
double z = 2.5*x;
assert(z == 17.5);
Зачем? Поскольку ваш компьютер может представлять все полномочия двух в качестве значений с плавающей запятой (пока эта мощность не превышает предел экспоненты, то есть), и он это сделает. Следовательно, все вышеприведенные вычисления точны, в константах нет ошибки округления. Все assert()
гарантируют успех.
Конечно, вы можете добиться такого же эффекта, выполнив манипуляции с битами, но текущее аппаратное обеспечение с плавающей запятой может выполнять умножение в течение наносекунды и правильно обрабатывать все специальные случаи. Если вы выполняете бит-бит, вы либо будете тратить время, либо обрабатывать особые случаи неправильно. Так что даже не пытайтесь.