Как сделать умножение и добавить три числа с фиксированной точкой - PullRequest
0 голосов
/ 15 марта 2020

Вот формулировка проблемы -

a: 5-битное представление, где 2 бита MSB - это целая часть, а 3 бита LSB - дробное b: 5-битное представление, где 2 бита MSB - это целая часть и 3 LSB биты являются дробными c: 11-битное представление, где бит MSB является целой частью, а 10 битов LSB являются дробными

Я пытаюсь написать C код для выполнения:

d = a * b + c

Как это сделать оптимально, какие структуры данных использовать et c

Спасибо, добавив еще несколько деталей - a & b - uint8_t (unsigned char) , c - это uint16_t (unsigned short int).

Принятие не менее 5 битов uint8_t для представления a & b Принятие не менее 11 битов unit_16_t для представления c

Использование соответствующих битовых масок для извлечения целых и дробных частей, таких как

a.int = (a >> 3) & 0x3
a.frac = a & 0x7
b.int = (b >> 3) & 0x3
b.frac = b & 0x7

Теперь я думаю, что я слишком усложняю решение путем разделения целых и дробных частей.

Предположим, я хочу умножить 2,31 на 1,05.

Мы можем умножить 231 на 105 и поделить позже на 10000.

Таким образом, вам не нужно разделять целые и дробные части исходного действительного числа.

Вдоль эти строки, что является хорошим решением? // a - 5 бит, младшие 3 бита - дробная часть, старшие 2 бита - целая часть

// b - 5 бит, младшие 3 бита - дробная часть, старшие 2 бита - целая часть

// c - 11 бит, не менее 10 бит - дробная часть, MSB - целая часть

#define uint8_t (unsigned char)

#define uint16_t (unsigned short int)

uint16_t   compute(uint8_t a, uint8_t b, uint16_t c)
{
     uint16_t multval = a * b;  // the least 6 bits represent the fractional part, the upper 4 bits represent integer part
     uint8_t ab_int = multval >> 6; // integer part of a*b
     uint8_t ab_frac = multval & 0x3F; // fractional part of a*b
     uint16_t ab_adjusted = (ab_int << 10) | ab_frac;
     uint16 sum = c + ab_adjusted;
     return sum;
}

1 Ответ

0 голосов
/ 15 марта 2020

Умножение значений с фиксированной точкой точно такое же, как умножение целых чисел. Единственная сложность заключается в том, что вы должны отслеживать количество целых и дробных битов в результате.

Если у вас есть два 8-битных значения без знака, где нижние биты F_1 и F_2 двух значений являются битами дроби тогда 16-битное произведение будет иметь дробные биты F_1 + F_2. Аналогично, продукт будет иметь целые биты I_1 + I_2. Если вы правильно выровняли мультипликаторы в 8-битных контейнерах, тогда продукт также будет правильно выровнен в его 16-битных контейнерах.

Добавление сложнее. Вы должны выровнять основную точку аддендов перед выполнением сложения целых чисел, что означает, что они должны иметь одинаковое количество битов дроби (при условии, что они снова выровнены по правому краю). Вы можете сделать это sh, сдвинув операнд с большим количеством битов дроби вправо (что жертвует точностью и разрешением) или сдвинув значение с меньшим количеством битов дроби вправо (что означает, что вам нужно больше общих битов для суммы). Выбор за вами.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...