Всякий раз, когда вы добавляете два номера с фиксированной точкой, вам может понадобиться бит переноса, чтобы правильно представлять результат. По этой причине при добавлении двух 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
свойства определяют правила для выполнения арифметических операций над 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
ProductMode
свойство a
установлено в KeepMSB
в то время как остальные fimath
свойства используют значения по умолчанию.Примечание
Для получения дополнительной информации о fimath
объект, его свойства и их значения по умолчанию, см. «Свойства объекта fimath».
Следующая таблица показывает рост разрядности fi
объекты, A
и B
, когда их SumMode
и ProductMode
свойства используют значение по умолчанию fimath
значение, FullPrecision
.
A | B | Сумма = A + B | Prod = A * B | |
---|---|---|---|---|
Формат | fi(vA,s1,w1,f1) | fi(vB,s2,w2,f2) | — | — |
Знак | s1 | s2 | Ssum = (s1 || s2 ) | Sproduct = (s1 || s2 ) |
Целочисленные биты | I1 = w1-f1-s1 | I2= w2-f2-s2 | Isum = max(w1-f1, w2-f2) + 1 - Ssum | Iproduct = (w1 + w2) - (f1 + f2) |
Дробные биты | f1 | f2 | Fsum = max(f1, f2) | Fproduct = f1 + f2 |
Всего бит | w1 | w2 | Ssum + Isum + Fsum | w1 + 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
свойства 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 | Округлится до ближайшего представимого числа в направлении нуля. | Низко |
| Нет |