как кто-то может разделить двойное число или число, умноженное на два?

0

Я знаю с нормальными целыми числами, которые вы можете разделить на бит-сдвиг вправо. Мне интересно, есть ли простой способ сделать то же самое с числами, которые не являются целыми числами.

  • 0
    Как бы вы поделили 221/13, сдвинув бит вправо?
  • 0
    Вы имеете в виду полномочия двух, верно?
Показать ещё 3 комментария
Теги:

3 ответа

4
Лучший ответ

ldexp, ldexpf и ldexpl делают это для удвоений, поплавков и длинных удвоений соответственно. В качестве альтернативы, если у вас есть определенная сила двух в виду (скажем, 4), лучше всего просто разделить обычный способ:

whatever / 4
0

Существует функция 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; ,

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() гарантируют успех.

Конечно, вы можете добиться такого же эффекта, выполнив манипуляции с битами, но текущее аппаратное обеспечение с плавающей запятой может выполнять умножение в течение наносекунды и правильно обрабатывать все специальные случаи. Если вы выполняете бит-бит, вы либо будете тратить время, либо обрабатывать особые случаи неправильно. Так что даже не пытайтесь.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню