Наиболее эффективная линейная интерполяция с использованием целочисленной дроби
Я играю с таблицами прямого цифрового синтеза на Atmega328.
Учитывая 8-битное дробное значение F и два 8-битных значения A, B, что будет наиболее эффективным способом для вычисления линейного интерполированного значения между A и B? Я могу думать о двух методах:
Альтернатива 1: интерполированное значение = ((A << 8) + (B - A) * F) >> 8
(Будет работать только когда B >= A, но я мог бы обернуть его в if/else и поменять местами A и B, если A > B)
Альтернатива 2: интерполированное значение = A + (B - A) * (F / 256)
Имеет ли значение, какой я выберу, или компилятор оптимизирует их одинаково?
Есть ли еще лучший метод, который не требует умножения или деления?
РЕДАКТИРОВАТЬ: Изменен знаменатель в alternative 2
от 255
в 256
1 ответ
При условии, что
F
в 1/256 за счет (и не может полностью выразить 1)A
,B
а такжеF
являютсяuint8_t
линейная интерполяция может быть
uint8_t I = A + (uint8_t)(((int16_t)(B-A) * F) >> 8)
Если ты хочешь это 255
выражает 1.0
тогда вы должны разделить на 255 вместо сдвига, но я думаю, я бы справился с one case
по-другому. например, используя 16 бит для F
и проверьте наличие старшего байта перед использованием вышеуказанной формулы с младшим байтом, если он меньше единицы.
Вышеуказанная строка почти такая же, как у альтернативной, но так как A
а также B
Если значение равно 8 битам, то интерполированный результат не может превышать 8-битный диапазон, поэтому сложение можно выполнить с помощью uint8_t.
Ваш вариант 2 всегда получает A
как результат со второго мультипликатора (F/256
) всегда ноль.