CORDIC算法
本示例介绍了Julia编程语言中CORDIC算法的实现,用于计算三角函数(正弦和余弦)。 而不使用标准功能。
导言
CORDIC算法(来自坐标旋转数字计算机)是一种迭代数值方法,用于计算三角函数,双曲线和其他数学函数。 CORDIC最初是为导航系统开发的,在计算资源有限的情况下特别有用,因为它只使用加法,减法和移位,这些操作在硬件和软件上都能很好地工作。 在本例中,CORDIC用于计算给定角度的正弦和余弦值。
主要部分
安装和连接软件包
In [ ]:
import Pkg; Pkg.add("Printf")
In [ ]:
using Printf
功能 cordic
这是实现CORDIC算法的主要功能。 她的角度 alpha 以弧度和迭代次数为单位 iteration. 迭代次数会影响结果的准确性。 迭代次数越多,精度越高,但计算时间也越长。
In [ ]:
function cordic(alpha, iteration = 24)
# 如果角度大于2π,则在确定新标志时可能会出现标志失败。
newsgn = isodd(Int(floor(alpha / 2π))) ? 1 : -1
# 使角度范围[-π/2,π/2]
alpha < -π/2 && return newsgn * cordic(alpha + π, iteration)
alpha > π/2 && return newsgn * cordic(alpha - π, iteration)
# 预先计算的反正切2^(-j)的表,其中j=0,1,2,。..
angles = [
0.78539816339745, 0.46364760900081, 0.24497866312686, 0.12435499454676,
0.06241880999596, 0.03123983343027, 0.01562372862048, 0.00781234106010,
0.00390623013197, 0.00195312251648, 0.00097656218956, 0.00048828121119,
0.00024414062015, 0.00012207031189, 0.00006103515617, 0.00003051757812,
0.00001525878906, 0.00000762939453, 0.00000381469727, 0.00000190734863,
0.00000095367432, 0.00000047683716, 0.00000023841858, 0.00000011920929,
0.00000005960464, 0.00000002980232, 0.00000001490116, 0.00000000745058]
# 缩放因子Kn的表,在最后考虑
Kvalues = [
0.70710678118655, 0.63245553203368, 0.61357199107790, 0.60883391251775,
0.60764825625617, 0.60735177014130, 0.60727764409353, 0.60725911229889,
0.60725447933256, 0.60725332108988, 0.60725303152913, 0.60725295913894,
0.60725294104140, 0.60725293651701, 0.60725293538591, 0.60725293510314,
0.60725293503245, 0.60725293501477, 0.60725293501035, 0.60725293500925,
0.60725293500897, 0.60725293500890, 0.60725293500889, 0.60725293500888]
# 我们根据迭代次数选择缩放级别的值。
Kn = Kvalues[min(iteration, length(Kvalues))]
# 向量的初始值为[cos(0),sin(0)] = [1, 0]
v = [1, 0]
poweroftwo = 1 # 2的幂,2^0=1,随着每次迭代而变化
angle = angles[1] # 当前旋转角度
# CORDIC的主要迭代周期
for j = 0:iteration-1
if alpha < 0
sigma = -1 # 逆时针转动
else
sigma = 1 # 顺时针转动
end
factor = sigma * poweroftwo # 旋转矩阵的系数
# 角度atan(2^(-j))的旋转矩阵,以CORDIC形式编写
R = [1 -factor
factor 1]
# 将向量v乘以矩阵R(旋转向量)
v = R * v
# 为下一次迭代更新剩余角度的值
alpha -= sigma * angle
# 移动到下一个两次方
poweroftwo /= 2
# 为下一次迭代更新角度
if j + 2 > length(angles)
angle /= 2 # 如果桌子结束,将角度减少一半。
else
angle = angles[j + 2] # 否则,我们从表中取以下角度
end
end
# 我们应用一个缩放因子来获得真实值。
v .*= Kn
return v # 我们返回[cos(alpha),sin(alpha)]
end
Out[0]:
功能 test_cordic
此函数用于检查算法的操作。 它输出各种角度的正弦和余弦值(以度和弧度为单位),并将它们与内置的Julia函数进行比较。
In [ ]:
function test_cordic()
println(" x sin(x) Δsin cos(x) Δcos ")
# 以15°为增量检查-90°至+90°的角度
for θ in -90:15:90
# 将度数转换为弧度并运行CORDIC函数
cosθ, sinθ = cordic(deg2rad(θ))
# 我们以以下格式打印值:角度,sin,正弦误差,余弦误差
@printf("%+05.1f° %+.8f (%+.8f) %+.8f (%+.8f)\n",
θ, sinθ, sinθ - sind(θ), cosθ, cosθ - cosd(θ))
end
println("\nx(rad)sin(x)Δsin cos(x)Δcos ")
# 检查弧度中的某些角度
for θr in [-9, 0, 1.5, 6]
cosθ, sinθ = cordic(θr)
@printf("%+3.1f %+.8f (%+.8f) %+.8f (%+.8f)\n",
θr, sinθ, sinθ - sin(θr), cosθ, cosθ - cos(θr))
end
end
Out[0]:
In [ ]:
test_cordic()
结论
在这个例子中,我们研究了Julia中CORDIC算法的实现,用于计算正弦和余弦的值。 该算法允许您仅依靠简单的算术运算来避免使用复杂的运算。 这使得它在计算能力有限的系统中特别有用。 我们还对实现进行了测试,将其与内置函数进行了比较,并确保结果与参考结果接近,这证实了实现的正确性。
该示例是使用[Rosetta代码]的材料开发的(https://rosettacode.org/wiki/CORDIC )