## 定点算术运算

### 定点算术

#### 加减法

```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```

#### 乘法

`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```

#### 与其他内置数据类型的数学运算

`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```

```a = fi(pi); b = int8(2) * a```
```b = 6.2832 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 24 FractionLength: 13```

`fi` 与逻辑数据类型之间进行算术运算时，逻辑值被视为值为 0 或 1 且字长为 1 的无符号 `fi` 对象。该运算的结果是 `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` 对象执行算术运算的规则，包括数学、舍入和溢出属性。`fi` 对象可以有局部 `fimath` 对象，它也可以使用默认 `fimath` 属性。您可以使用 `setfimath``fimath` 对象附加到 `fi` 对象。您也可以在创建时在 `fi` 构造函数中指定 `fimath` 属性。当 `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```
`a``ProductMode` 属性设置为 `KeepMSB`，而其余的 `fimath` 属性使用默认值。

### 位增长

ABSum = A+BProd = A*B

```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```

### 控制位增长

#### 使用 fimath

```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```

`fi` 对象 `a` 具有局部 `fimath` 对象 `F``F` 指定和的字长和小数长度。在默认 `fimath` 设置下，输出 `c` 通常字长为 9，小数长度为 0。但是，由于 `a` 具有局部 `fimath` 对象，因此生成的 `fi` 对象的字长为 8，小数长度为 0。

```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。

#### 下标赋值

```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) 指示下标向量 `(:)` 处的值发生更改。但是，输出 `acc``numerictype` 保持不变。由于 `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```

`acc``numerictype``for` 循环的每次迭代中保持不变。

```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```

### 溢出和舍入

#### 舍入

`ceil` 朝正无穷方向舍入到最邻近的可表示数字。大的正向偏置
`convergent`舍入到最邻近的可表示数字。在舍入机会均等的情况下，`convergent` 舍入到最邻近的偶数。这种方法是由工具箱提供的最小偏置舍入方法。无偏置
`floor`朝负无穷方向舍入到最邻近的可表示数字，相当于 2 的补码截断。大的负偏置
`nearest`舍入到最邻近的可表示数字。在舍入机会均等的情况下，`nearest` 朝正无穷方向舍入到最邻近的可表示数字。此舍入方法是 `fi` 对象创建和 `fi` 算术的默认值。中等小的正向偏置
`round`

• 将正数朝正无穷方向舍入到最邻近的可表示数字。

• 将负数朝负无穷方向舍入到最邻近的可表示数字。

• 对于具有负值的样本，为小的负偏置

• 对于具有均匀分布的正值和负值的样本，无偏置

• 对于具有正值的样本，为小的正向偏置

`fix`舍入到零方向上最邻近的可表示数字。
• 对于具有负值的样本，为大的正向偏置

• 对于具有均匀分布的正值和负值的样本，无偏置

• 对于具有正值的样本，为大的负偏置