Оптимизация: вдвое больше

0

У меня есть два метода интерполяции, которые я использую в некоторых своих программах...

__forceinline double InterpolateDouble(double dOldVal, double dOldMin, double dOldMax, double dNewMin, double dNewMax) 
{ 
    return (((dOldVal - dOldMin) * (dNewMax - dNewMin)) / (dOldMax - dOldMin)) + dNewMin; 
}

__forceinline int InterpolateInteger(int nOldVal, int nOldMin, int nOldMax, int nNewMin, int nNewMax) 
{ 
    return (int)InterpolateDouble((double)nOldVal, (double)nOldMin, (double)nOldMax, (double)nNewMin, (double)nNewMax); 
}

Метод InterpolateInteger() просто вызывает метод InterpolateDouble() для поддержания некоторой дробной точности. Является ли преобразование из целого числа удвоенным, и есть ли способ получить точный результат, используя только целые числа (без кастингов)?

  • 0
    Вы спрашиваете о стоимости процессора для выполнения преобразования, или вас беспокоит что-то еще?
  • 0
    В основном меня беспокоит любое усечение, связанное с целочисленными делениями. Я не уверен, будут ли одинаковые результаты достигнуты со всеми целыми числами, поэтому я просто преобразовал в double. Производительность на самом деле не проблема, но было бы неплохо ускорить ее. Я знаю, что есть хит производительности с int и float и back ... не уверен насчет двойников.
Показать ещё 1 комментарий
Теги:
optimization
interpolation

3 ответа

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

Существует риск переполнения при умножении перед делением, поскольку ваш код здесь. Вы должны проверить возможные значения ваших входов, в дополнение к возможным промежуточным вычислениям умножения в коде, чтобы определить, будет ли тип int всегда достаточным для расчета. Усечение произойдет с целым делением, но если вы хотите получить целочисленный результат, ожидаемый. Преобразование из int в double является тривиальным с точки зрения процессора, так как перед вычислением перед ним стоит 0.

  • 0
    Можете ли вы объяснить, что вы имеете в виду, что «перед вычислением стоит перед 0 целое число»?
  • 0
    На самом деле, я путал «длинный» с двойным. Вы ничего не получите, приведя свои целые числа к двойным числам с плавающей запятой, за исключением того, что потенциально можете добавить некоторые неточности, присущие с плавающей запятой, к вашему преобразованию. Для начала у вас есть два целых числа, и вы только умножаете, вычитаете и делите их, а затем в любом случае возвращаете к целому числу. Нет причин не делать вычисления в виде целых чисел. Я имею в виду, что преобразование из int в long означает только то, что 32-битному int предшествует 0, чтобы получить 64-битное int.
Показать ещё 1 комментарий
0

Если вы после максимальной оптимизации и точки интерполяции зафиксированы, вы можете использовать следующее целочисленное выражение:

(dOldVal * dNewDelta + dNewMin * dOldDelta - dOldMin * dNewDelta) / dOldDelta

которая имеет вид (A * X + B)/C, где A, B и C - три предварительно вычисленные целочисленные константы. Это даст точные целочисленные ответы.

Альтернативно, используйте A * X + B с предварительно рассчитанными коэффициентами с двойной точностью, но стратегия округления должна быть тщательно скорректирована.

Еще одна возможность состоит в том, чтобы перемасштабировать и обогнуть коэффициенты A и B с использованием силы 2, давая быструю безделевую целочисленную формулу формы

(A * X + B) >> p

(стратегия округления также деликатна).

0

Это не преобразование из int в double, о котором вы должны беспокоиться. Это преобразование (усечение) обратно из double в int после завершения работы. Рассмотрим интерполяцию [0, 500] на [0, 1]. В этом случае, как только вы выполните интерполяцию double, число будет 1 выход для 500 входных сигналов и меньше единицы для ввода 0-499. Таким образом, ввод 0-499 приведет к выходу 0 после усечения, а 500 приведет к 1.

Ещё вопросы

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