Как исправить положение двоичной точки в беззнаковом 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 ответа
Краткий ответ: сдвиг влево.
Длинный ответ:
Номера с фиксированной точкой хранятся как целые числа, обычно
int
, который является самым быстрым целочисленным типом для конкретной платформы.Обычное целое число без дробных битов обычно называется
Q0
,Q.0
или жеQX.0
где X - общее количество бит базового типа хранилища (обычноint
).Конвертировать между разными
Q.X
форматы, сдвиг влево или вправо. Например, чтобы преобразовать 5 вQ0
до 5 в Q4, сдвиньте его влево на 4 бита или умножьте на 16.Обычно полезно найти или написать небольшую библиотеку с фиксированной точкой, которая выполняет базовые вычисления, например
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)
биты.- Разделение похоже, вы получаете
Q.(X-Y)=Q.X*Q.Y
сформировать стандарт/
оператор, и получить результат вQ.Z
Формат вы сдвигаете дивиденды перед делением. Отличительной особенностью является то, что деление является дорогостоящей операцией, и не так просто написать быструю с нуля. - Помните о поддержке вашей платформы двумя словами, это сделает вашу жизнь намного проще. С арифметикой двойного слова, результат
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>
, Как бы вы определили свой результат? Шаблоны выдадут вам ошибку времени компиляции, если вы попытаетесь это сделать.