Engee中的定点算术
在数值计算的世界中,绝大多数任务都是使用浮点数来解决的(漂浮物32, 漂浮64`然而,在诸如微控制器、Dsp、Fpga或Asic的实际系统中,使用浮子类型可能是不希望的或不可能的。 例如,在STM32系列微控制器中,基本型号没有硬件支持。 `浮子,浮子,并且其中的浮点运算比整数运算执行得慢得多。 在这种情况下,使用定点算术(定点),其中分数值以整数格式编码,具有分数部分的预定义长度。
定点数字(定点)是一种使用普通整数和预定义比例(小数部分的位数)表示分数值的方法。 而不是资源密集型浮点算术(漂浮物32, 漂浮64),这里使用一个简单的整数格式,其中"二进制逗号"被移位一组位数。
例如,如果小数部分的长度为 ,那个数字 存储为整数值 ,因为根据重新计算内部值的公式(存储_integer)实时(real_value) 我们得到 . 公式显示内部值被保留并且等于 ,并在计算它被解释为 .
- 这样的算术具有以下优点
-
-
更低的资源消耗(与微控制器、Fpga和Asic相关);
-
控制精度和值范围;
-
可预测的舍入行为footnote:common_2[*舍入*是将值减少到可接受的形式的过程,考虑到有限的小数部分(
f). 由于定点数不能准确表示所有可能的小数值,因此在运算过程中,结果会根据给定策略四舍五入(例如,到最近的值或截断)。]和overflowingfootnote:common_3[*Overflow*是一个过程,如果计算结果超过给定字大小允许的限制(W)和熟悉(`S`在此类情况下,使用溢出处理策略:饱和,其中值被限制为允许的最大/最小值,或者截断或误差输出。]; -
支援服务 代码生成器 Verilog(HDL)和C上的。
-
阅读文章中有关定点算术的更多信息 guide/hdl-fixed-point-arithmetic.adoc#fixed-point-arithmetic
在Engee中使用固定点
*Engee*使用自己的包与定点工作。 EngeeFixedPoint。jl,它取代了标准的Julia包 FixedPointNumbers。jl. 与经典包装不同, EngeeFixedPoint。jl 它提供了先进的功能和精确控制定点数的表示和行为,这在资源有限的系统中尤为重要,当将计算转移到 HDL,以及在精密任务。
包裹 EngeeFixedPoint。jl 它是一个标准的*Engee*包,默认情况下包含在用户环境中,因此它不需要显式调用(通过 进口/使用)在代码中。
|
在*Engee*中,定点数的类型如下所示:
Fixed{S, W, f, T} <: FixedPoint
哪里:
-
S-一个标志(1-签名脚注:common[Signed-可以存储正值和负值。 例子::Int8,Int16,固定{1, 16, 4}.],0-Unsigned注:common_1[Unsigned-只能存储正值和零。 例子::UInt8,UInt16,固定{0, 16, 4}.]); -
W-字的长度(分配给数字的位数); -
f-小数部分的长度(每个小数部分的位数,比例); -
T-定点数的整数表示类型(Int32,UInt64等等)。
此格式允许您准确指定数字将如何存储、解释和参与计算,因为在数据处理的所有阶段都有安全的键入和清晰的行为。
为方便起见 EngeeFixedPoint。jl 它提供了几种设置固定点类型的方法,从完整的手动分配到自动输出。
S, W, f, T = 1, 25, 10, Int32
dt1 = Fixed{S, W, f, T}
dt2 = fixdt(S, W, f)
dt3 = fixdt(Fixed{S, W, f})
dt4 = fixdt(dt2)
println(dt1 == dt2 == dt3 == dt4) # true
哪里:
-
dt1=固定{S, W, f, T}-完整的手册描述; -
dt2=fixdt(S,W,f)-简化创建,类型 它是自动选择的; -
dt3=fixdt(固定{S, W, f})-获取基于现有描述的类型; -
dt4=fixdt(dt2)-重用,从现有类型创建副本。
所有这些选项都创建相同的类型。 固定{1, 25, 10, Int32},并可根据任务使用:
-
完整描述(
dt1当您需要控制所有参数时,这很方便。; -
简化的方式(
dt2)适用于典型情况,并减少了代码; -
从类型获取类型(
dt3)生成代码或键入数据时很有用; -
再利用(
dt4)有助于使用参数化结构,而无需重新输入参数。
类型构造函数 固定
接下来,让我们来看看在*Engee*中使用固定点的具体场景。
所以,你可以直接设置类型并传递值。:
x = Fixed{1, 15, 2}(25)
结论:
fi(6.25, 1, 15, 2)
这意味着 -整数表示(存储_integer),而真正的价值(real_value)将等于 根据公式 .
固定{S, W, f}(i::T)
基于整数表示创建固定点的构造函数 固定{S, W, f}(i::T) 接受:
-
格式参数:
S(熟悉度),W(以位为单位的宽度),f(小数部分); -
整数值
i像T(内部表示)。
S,W,f=1,15,2#有符号,15位,2小数位
i = 25
X=Fixed{S,W,f}(i)#从整数创建
结论:
菲(6.25, 1, 15, 2) # 等效表示
固定{S, W, f, T1}(i::T2)
构造函数与前一个类似,能够显式指定存储类型。 类型将根据参数自动选择。 S, W, f,无论指定 T1.
T = Int128
x = Fixed{S, W, f, T}(i) # 指示存储类型
结论:
菲(6.25, 1, 15, 2) # 结果是相同的
FixedPointNumbers的构造函数。jl
尽管使用了新包 EngeeFixedPoint。jl,它仍然具有与包的兼容性 FixedPointNumbers。jl 以支持多个构造函数。 仅支持签名类型。
支持:
-
固定{T, f}(i::整数,_)-整数表示的构造函数。 接受类型T和参数f; -
固定{T, f}(价值)-真实世界的值构造函数(浮子,浮子).
例子::
T = Int32
x1 = Fixed{T, f}(i, nothing) # 从整数
x2 = Fixed{T, f}(i) # 从一个实数
结论:
6.25#第一个构造函数的结果
25.0#第二个构造函数的结果
使用数组和矩阵
该库完全支持定点数的向量和矩阵运算。 所有操作都会保存元素类型,并自动将指定的精度参数应用于数组的所有元素。
向量资料
创建和使用一维数组。 定点参数应用于所有元素:
s, w, f = 1, 62, 7 # 有符号类型,62位,7位小数部分
v = [1, 2, 3] # 资料来源
# 不同的创作方式:
x1 = fi(v, s, w, f) # 指定显式参数
x2 = fi(v, fixdt(s, w, f)) # 通过数据类型
x3 = fi(v, s, w) # 具有自动小数部分检测功能
println(x1)
println(x1 == x2)
println(x3)
结论:
Fixed{1, 62, 7}[1.0, 2.0, 3.0]
true
Fixed{1, 62, 59}[1.0, 2.0, 3.0]
复杂矩阵
全面支持多维数组中的复数:
s, w, f = 1, 62, 7
m = [im 2.5; -1.2im 25-im]
# 创造的工作方法:
x1 = fi(m, s, w, f) # 指定显式参数
x2 = fi(m, fixdt(s, w, f)) # 通过数据类型
println(x1)
println(x1 == x2)
结论:
Complex{Fixed{1, 62, 7, Int64}}[fi(0.0, 1, 62, 7) + fi(1.0, 1, 62, 7)*im fi(2.5, 1, 62, 7) + fi(0.0, 1, 62, 7)*im; fi(0.0, 1, 62, 7) - fi(1.203125, 1, 62, 7)*im fi(25.0, 1, 62, 7) - fi(1.0, 1, 62, 7)*im]
true
数学运算
系统自动选择操作结果的最佳格式,保持准确性并防止溢出。 支持所有基本算术运算(加法,减法,乘法,除法):
x1 = fi(1.5, 0, 15, 3)
x2 = fi(1.5, 1, 25, 14)
y1 = x1+x2
y2 = x1-x2
y3 = x1*x2
y4 = x1/x2
println(y1)
println(y2)
println(y3)
println(y4)
println(typeof(y1))
println(typeof(y2))
println(typeof(y3))
println(typeof(y4))
println(x1 == x2)
println(x1 <= x2)
println(x1 > x2)
结论:
3.0
0.0
2.25
0.0
Fixed{1, 28, 14, Int32}
Fixed{1, 28, 14, Int32}
Fixed{1, 40, 17, Int64}
Fixed{1, 25, -11, Int32}
true
true
false
四舍五入
各种舍入策略允许您控制计算的准确性。 默认情况下,使用RoundNearestTiesUp。
x = fi(1.5, 1, 14, 3) # 有符号,14位,3小数位
println(round(x)) # 2.0-舍入到最接近的整数(1.5→2)
println(trunc(x)) # 1.0-删除小数部分
println(ceil(x)) # 2.0-四舍五入到一个更大的整数
println(floor(x)) # 1.0-向下舍入到较小的整数
哪里:
-
圆形-银行四舍五入(至最接近的偶数0.5); -
[医]-丢弃小数部分; -
齐尔-总是在大的方式; -
楼层-总是在一个较小的方向。
类型转换(conversion)
与其他库交互时,转换为标准数据类型非常有用。 转换时,将舍入规则考虑在内。
x = fi(1.5, 1, 12, 4)
y1 = Int64(x)
y2 = UInt8(x)
y3 = Float64(x)
y4 = convert(fixdt(0, 5, 2), x)
println(y1)
println(y2)
println(y3)
println(y4)
println(typeof(y1))
println(typeof(y2))
println(typeof(y3))
println(typeof(y4))
结论:
1
1
1.5
1.5
Int64
UInt8
Float64
Fixed{0, 5, 2, UInt8}
结论
因此,包 EngeeFixedPoint。jl 提供以下优点:
-
扩展型系统:
-
完全支持有符号和无符号数字;
-
任意位深度(任意位大小,不仅仅是8/16/32/64/128);
-
灵活调整小数部分(包括负值和情况下 ,小数部分的长度,比单词的长度长 ).
-
-
改进类型推断规则:
-
依赖于平台的代码生成:
-
目标平台的不同类型继承规则(C或Verilog);
-
溢出128位边界时的可预测行为(与类似物不同)。
-
-
高级功能: