Наиболее эффективная линейная интерполяция с использованием целочисленной дроби

Я играю с таблицами прямого цифрового синтеза на 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) всегда ноль.

Другие вопросы по тегам