Выполнение арифметики с фиксированной точкой

Арифметика с фиксированной точкой

Сложение и вычитание

Всякий раз, когда вы добавляете два номера с фиксированной точкой, вам может понадобиться бит переноса, чтобы правильно представлять результат. По этой причине при добавлении двух B-битных чисел (с тем же масштабированием) полученное значение имеет дополнительный бит по сравнению с двумя используемыми операндами.

a = fi(0.234375,0,4,6);
c = a+a
c = 

    0.4688

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Unsigned
            WordLength: 5
        FractionLength: 6
a.bin
ans =

1111
c.bin
ans =

11110

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

a = fi(pi,1,16,13);
b = fi(0.1,1,12,14);
c = a + b
c = 

    3.2416

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 18
        FractionLength: 14

Умножение

В целом полная точность продукта требует размера слова, равной сумме размера слова операндов. В следующем примере обратите внимание, что размер слова продукта c равен размеру слова a плюс размер слова b. Длина дроби c также равно длине дроби a плюс длина дроби b.

a = fi(pi,1,20), b = fi(exp(1),1,16)
a = 

    3.1416

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 20
        FractionLength: 17

b = 

    2.7183

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 16
        FractionLength: 13
c = a*b
c = 

    8.5397

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 36
        FractionLength: 30

Математика с другими встроенными типами данных

Обратите внимание, что в C результат операции между целочисленным типом данных и двойным типом данных способствует двойному. Однако в MATLAB®, результатом операции между встроенным целочисленным типом данных и двойным типом данных является целое число. В этом отношении fi объект ведет себя как встроенные целочисленные типы данных в MATLAB.

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

a = fi(pi);
a = 

    3.1416

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 16
        FractionLength: 13
b = 0.5 * a
b = 

    1.5708

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 32
        FractionLength: 28

При выполнении арифметики между fi и один из встроенных целочисленных типов данных, [u]int[8, 16, 32], размер слова и сигнальность целого числа сохранены. Результатом операции является fi.

a = fi(pi);
b = int8(2) * a
b = 

    6.2832

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 24
        FractionLength: 13

При выполнении арифметики между fi логический тип данных, логический тип рассматривается как неподписанный fi объект со значением 0 или 1 и размером слова 1. Результатом операции является fi объект.

a = fi(pi);
b = logical(1);
c = a*b
c = 

    3.1416

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 17
        FractionLength: 13

Объект fimath

fimath свойства определяют правила для выполнения арифметических операций над fi объекты, включая математические, округляющие и переполненные свойства. A fi объект может иметь локальную fimath объект, или он может использовать fimath по умолчанию свойства. Можно прикрепить fimath объект в fi объект при помощи setfimath. Также можно задать fimath свойства в fi конструктор при создании. Когда fi объект имеет локальную fimath , а не использование свойств по умолчанию, отображение fi объект показывает fimath свойства. В этом примере a имеет ProductMode свойство, заданное в конструкторе.

 a = fi(5,1,16,4,'ProductMode','KeepMSB')
a = 

     5

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 16
        FractionLength: 4

        RoundingMethod: Nearest
        OverflowAction: Saturate
           ProductMode: KeepMSB
     ProductWordLength: 32
               SumMode: FullPrecision
The ProductMode свойство a установлено в KeepMSB в то время как остальные fimath свойства используют значения по умолчанию.

Примечание

Для получения дополнительной информации о fimath объект, его свойства и их значения по умолчанию, см. «Свойства объекта fimath».

Рост разрядности

Следующая таблица показывает рост разрядности fi объекты, A и B, когда их SumMode и ProductMode свойства используют значение по умолчанию fimath значение, FullPrecision.

 ABСумма = A + BProd = A * B
Форматfi(vA,s1,w1,f1)fi(vB,s2,w2,f2)
Знакs1s2Ssum = (s1|| s2)Sproduct = (s1|| s2)
Целочисленные битыI1 = w1-f1-s1I2= w2-f2-s2Isum = max(w1-f1, w2-f2) + 1 - SsumIproduct = (w1 + w2) - (f1 + f2)
Дробные битыf1f2Fsum = max(f1, f2) Fproduct = f1 + f2
Всего битw1w2Ssum + Isum + Fsumw1 + w2

Этот пример показывает, как рост разрядности может произойти в for-цикл.

T.acc = fi([],1,32,0);
T.x = fi([],1,16,0);

x = cast(1:3,'like',T.x);
acc = zeros(1,1,'like',T.acc);

for n = 1:length(x)
    acc = acc + x(n)
end
acc = 

     1
      s33,0

acc = 

     3
      s34,0

acc = 

     6
      s35,0
Область размера слова acc увеличивается с каждой итерацией цикла. Это увеличение вызывает две проблемы: Одна из них заключается в том, что генерация кода не позволяет изменять типы данных в цикле. Другое состоит в том, что, если цикл достаточно длинный, у вас заканчивается память в MATLAB. Смотрите Управление Ростом разрядности для некоторых стратегий, чтобы избежать этой проблемы.

Управление ростом разрядности

Использование fimath

Путем определения fimath свойства fi объект, можно управлять ростом разрядности, так как операции выполняются над объектом.

F = fimath('SumMode', 'SpecifyPrecision', 'SumWordLength', 8,...
 'SumFractionLength', 0);
a = fi(8,1,8,0, F);
b = fi(3, 1, 8, 0);
c = a+b
c = 

    11

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 8
        FractionLength: 0

        RoundingMethod: Nearest
        OverflowAction: Saturate
           ProductMode: FullPrecision
               SumMode: SpecifyPrecision
         SumWordLength: 8
     SumFractionLength: 0
         CastBeforeSum: true

The fi a объекта имеет локальную fimath F объекта. F задает размер слова и длину дроби суммы. Под fimath по умолчанию настройки, выход, c, обычно имеет размер слова 9 и длину дроби 0. Однако из-за a имел локальную fimath объект, результат fi объект имеет размер слова 8 и длину дроби 0.

Можно также использовать fimath свойства для управления ростом разрядности в for-цикл.

F = fimath('SumMode', 'SpecifyPrecision','SumWordLength',32,...
'SumFractionLength',0);
T.acc = fi([],1,32,0,F);
T.x = fi([],1,16,0);

x = cast(1:3,'like',T.x);
acc = zeros(1,1,'like',T.acc);

for n = 1:length(x)
    acc = acc + x(n)
end
acc = 

     1
      s32,0

acc = 

     3
      s32,0

acc = 

     6
      s32,0

В отличие от когда T.acc пользовался значением по умолчанию fimath свойства, рост разрядности acc теперь ограничено. Таким образом, размер слова acc остается в 32.

Подписанное назначение

Другой способ управления ростом разрядности - это использование подписанного назначения. a(I) = b присваивает значения b в элементы a задается вектором индекса, I, при сохранении numerictype от a.

T.acc = fi([],1,32,0);
T.x = fi([],1,16,0);

x = cast(1:3,'like',T.x);
acc = zeros(1,1,'like',T.acc);

% Assign in to acc without changing its type
for n = 1:length(x)
    acc(:) = acc + x(n)
end

acc (:) = acc + x (n) диктует, что значения в векторе индекса, (:), изменить. Однако numerictype от выхода acc остается прежним. Потому что acc является скаляром, вы также получаете тот же выход, если используете (1) как вектор индекс.

  for n = 1:numel(x)
    acc(1) = acc + x(n);
  end
acc = 

     1
      s32,0

acc = 

     3
      s32,0

acc = 

     6
      s32,0

The numerictype от acc остается тем же самым при каждой итерации for-цикл.

Подписанное назначение может также помочь вам контролировать рост разрядности в функции. В функции cumulative_sum, а numerictype от y не изменяется, но значения в элементах, заданных n,

function y = cumulative_sum(x)
% CUMULATIVE_SUM Cumulative sum of elements of a vector.
%
%   For vectors, Y = cumulative_sum(X) is a vector containing the
%   cumulative sum of the elements of X.  The type of Y is the type of X.
    y = zeros(size(x),'like',x);
    y(1) = x(1);
    for n = 2:length(x)
        y(n) = y(n-1) + x(n);
    end
end
y = cumulative_sum(fi([1:10],1,8,0))
y = 

     1     3     6    10    15    21    28    36    45    55

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 8
        FractionLength: 0

Примечание

Для получения дополнительной информации о назначении по подписке смотрите subsasgn функция.

аккумуляторы и аккумуляторы

Другой способ, которым вы можете управлять ростом разрядности, - это использование accumpos и accumneg функции для выполнения операций сложения и вычитания. Аналогично использованию подписанного назначения, accumpos и accumneg сохранить тип данных одного из его входных fi объекты, позволяя вам задать метод округления и действие переполнения в вход значениях.

Для получения дополнительной информации о том, как реализовать accumpos и accumneg, см. «Избегайте многословных операций в сгенерированном коде»

Переполнения и округление

При выполнении арифметики с фиксированной точкой учитывайте возможность и последствия переполнения. The fimath объект задает режимы переполнения и округления, используемые при выполнении арифметических операций.

Переполнение

Переполнения могут произойти, когда результат операции превышает максимальное или минимальное представимое значение. The fimath объект имеет OverflowAction свойство, которое предлагает два способа борьбы с переливами: насыщение и перенос. Если вы задаете OverflowAction на saturateпереполнения насыщаются до максимального или минимального значения в области значений. Если вы задаете OverflowAction на wrap, любой перенос переполнения с использованием арифметики по модулю, если не подписано, или два переноса дополнения, если подписано.

Для получения дополнительной информации о том, как обнаружить переполнение, смотрите Underflow and Overflow Logging Using fipref.

Округление

При выборе метода округления необходимо учитывать несколько факторов, включая стоимость, смещение и возможность переполнения. Программное обеспечение Fixed-Point Designer™ предлагает несколько различных функций округления, удовлетворяющих требованиям вашего проекта.

Метод округления ОписаниеСтоимостьУклонВозможность переполнения
ceil Округлится до ближайшего представимого числа в направлении положительной бесконечности.НизкоБольшой позитивДа
convergentОкруглится до ближайшего представимого числа. В случае галстука convergent округляет до ближайшего четного числа. Этот подход является наименее смещенным методом округления, предоставленным тулбоксом.ВысокоБеспристрастныйДа
floorОкруглает до ближайшего представимого числа в направлении отрицательной бесконечности, эквивалентной усечению двух комплементов.НизкоБольшой минусНет
nearestОкруглится до ближайшего представимого числа. В случае галстука nearest округляет до ближайшего представимого числа в направлении положительной бесконечности. Этот метод округления является методом по умолчанию для fi создание и fi объектов арифметика.УмеренныйМалый позитивДа
roundОкруглится до ближайшего представимого числа. В случае галстука, round округи метода:
  • Положительные числа к ближайшему представляемому числу в направлении положительной бесконечности.

  • Отрицательные числа к ближайшему представляемому числу в направлении отрицательной бесконечности.

Высоко
  • Небольшой минус для отрицательных выборок

  • Объективный для выборок с равномерно распределенными положительными и отрицательными значениями

  • Малый положительный для положительных выборок

Да
fixОкруглится до ближайшего представимого числа в направлении нуля.Низко
  • Большой позитив для отрицательных выборок

  • Объективный для выборок с равномерно распределенными положительными и отрицательными значениями

  • Большой минус для положительных выборок

Нет