Как исправить положение двоичной точки в беззнаковом N-битном интергере?

Я работаю над разработкой алгоритма с фиксированной точкой в ​​C++. Я знаю, что для N-разрядного целого числа двоичное целое с фиксированной точкой представляется как U(a,b). Например, для 8-битного целого числа (то есть 256 выборок), если мы представим его в форме U(6,2), это означает, что двоичная точка находится слева от 2-го бита, начиная с правой части формы:

                   b5 b4 b3 b2 b1 b0 . b(-1) b(-2)

Таким образом, он имеет 6 целочисленных битов и 2 дробных бита. В C++ я знаю, что есть некоторые операторы сдвига битов, которые я могу использовать, но они в основном используются для сдвига битов входного потока, мой вопрос в том, как определить двоичное целое число с фиксированной запятой в форме, fix<6,2> или U(6,2). Все основные операции обработки будут выполняться в дробной части, и я просто нахожу способ сделать это исправление в C++. Любая помощь относительно этого будет оценена. Спасибо!

Пример: Предположим, у меня есть входной дискретный сигнал с 1024 точками выборки на оси x (сейчас просто подумайте, что этот входной сигнал исходит от некоторого датчика). Каждая из этих точек выборки имеет определенную амплитуду. Скажем, образец в момент времени 2(ось X) имеет амплитуду 3,67(ось Y). Теперь у меня есть переменная "int *input;" это берет пример 2, который в двоичном виде равен 0000 0100. Поэтому в основном я хочу сделать это как 00000.100, выполнив U(5,3) для образца 2 в C++. Так что я могу выполнять операции интерполяции на фракциях входного периода выборки или времени.

PS - я не хочу создавать отдельный класс или использовать для этого внешние библиотеки. Я просто хочу взять каждые 8 ​​бит из моего входного сигнала, выполнить исправление U (a, b) для него, после чего остальные операции выполняются в дробной части.

2 ответа

Решение

Краткий ответ: сдвиг влево.

Длинный ответ:

  1. Номера с фиксированной точкой хранятся как целые числа, обычно int, который является самым быстрым целочисленным типом для конкретной платформы.

  2. Обычное целое число без дробных битов обычно называется Q0, Q.0 или же QX.0 где X - общее количество бит базового типа хранилища (обычно int).

  3. Конвертировать между разными Q.X форматы, сдвиг влево или вправо. Например, чтобы преобразовать 5 в Q0 до 5 в Q4, сдвиньте его влево на 4 бита или умножьте на 16.

  4. Обычно полезно найти или написать небольшую библиотеку с фиксированной точкой, которая выполняет базовые вычисления, например a*b>>q а также (a<<q)/b, Потому что вы будете делать Q.X=Q.Y*Q.Z а также Q.X=Q.Y/Q.Z много и вам нужно конвертировать форматы при выполнении расчетов. Как вы могли заметить, используя нормальный * Оператор даст вам Q.(X+Y)=Q.X*Q.Yтак, чтобы соответствовать результату в Q.Z формат, вам нужно сдвинуть результат вправо (X+Y-Z) биты.

  5. Разделение похоже, вы получаете Q.(X-Y)=Q.X*Q.Y сформировать стандарт / оператор, и получить результат в Q.Z Формат вы сдвигаете дивиденды перед делением. Отличительной особенностью является то, что деление является дорогостоящей операцией, и не так просто написать быструю с нуля.
  6. Помните о поддержке вашей платформы двумя словами, это сделает вашу жизнь намного проще. С арифметикой двойного слова, результат a*b может быть в два раза больше a или же bчтобы вы не потеряли дальность действия a*b>>c, Без двойного слова, вы должны ограничить диапазон ввода a а также b чтобы a*b не переполняется Это неочевидно при первом запуске, но вскоре вы обнаружите, что вам нужно больше дробных бит или ярости, чтобы выполнить работу, и вам, наконец, нужно будет изучить справочное руководство по ISA вашего процессора.

пример:

float a = 0.1;// 0.1
int aQ16 = a*65536;// 0.1 in Q16 format
int bQ16 = 4<<16// 4Q16
int cQ16 = a*b>>16 // result = 0.399963378906250Q16 = 26212, 
                   // not 0.4Q16 = 26214 because of truncating error

Если это ваш вопрос:

Q. Должен ли я определить мое целое число с фиксированной двоичной точкой в ​​качестве шаблона, U<int a, int b>(int number), или нет, U(int a, int b)

Я думаю, что ваш ответ на этот вопрос: "Вы хотите определить операторы, которые принимают два целых числа с фиксированной двоичной точкой? Если это так, сделайте их шаблоном".

Шаблон просто немного сложнее, если вы не определяете операторы. Так что я бы оставил это.

Но если вы определяете операторы, вы не хотите иметь возможность добавлять U<4, 4> а также U<6, 2>, Как бы вы определили свой результат? Шаблоны выдадут вам ошибку времени компиляции, если вы попытаетесь это сделать.

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