【问题标题】:Using MATLAB to find Minimax Polynomial Approximation of Trigonometric Functions使用 MATLAB 求三角函数的 Minimax 多项式逼近
【发布时间】:2012-02-15 21:05:43
【问题描述】:

我正在尝试使用 MATLAB 中的 remez 交换算法找到正弦和余弦的极小极大多项式近似值。需要精确到 23 位,因为我正在为 IEEE-754 浮点实现正弦和余弦函数。

使用此链接here(请参阅第 8 页至第 15 页),给出了使用 Mathematica 和 Maple 查找多项式的说明,但是,我不确定如何为 MATLAB 推断这些方法。

根据表 3,我需要使用 5 阶或 6 阶多项式来获得大约 23 位(小数点后)的精度。

我计划首先将所有传入的 theta 范围缩小到 -pi/4 到 +pi/4 之间,然后根据需要执行正弦或余弦函数(最终目标是实现 exp(i*x) = cos(x) + i*sin(x)。

我自己也许可以按照本文的说明进行操作,但我不知道如何将 remez 函数用于我的目的。另外,我不明白为什么作者使用方程(6)(第 9 页),我也不明白 k 的方程(第 11 页)是如何确定的(2796201 来自哪里?)以及为什么定义我们希望得到的多项式形式最终变为 sin9x) = x + kx^3 + x^5*P(x^2)。

使用 firpm 函数会更好吗(因为 remez 已弃用)?

谢谢您,我们非常感谢您提供所有帮助和指导,并进行编辑以确保为我的问题提供最佳答案。

【问题讨论】:

  • 请注意,链接的论文已经在“优化浮点”部分中给出了 sin 在 [0,pi/4] 上的 minimax 近似值,因此您只需要在 [ 上找到 cos 的近似值0,pi/4],一切就绪。
  • 那你建议我怎么做?
  • 在上一个问题的答案中,您至少有一个指向 [0,pi/4] 上余弦的单精度极小极大近似值的良好指针:stackoverflow.com/questions/9265865/cosine-in-floating-point

标签: matlab math floating-point trigonometry


【解决方案1】:

我不会费心尝试开发您自己的近似值。更简单的是拿起 Hart 等人的“Computer Approximations”的副本。一个好的大学图书馆应该有它。 23 位大约是 7 个十进制数字,因此只需选择一个近似值,即可获得所需的准确度。您可以选择简单的多项式近似,也可以使用有理多项式,只要您能容忍除法,通常会更好一些。

范围缩小确实有意义,事实上,我在自己的工具中选择了相同的范围 (+/-pi/4),因为这种范围选择特别容易使用。

编辑:(使用在 Hart 中可以找到的近似值的示例。)

在这里,我将找到 sin(x) 的近似值,其中 x 位于区间 [0,pi/4] 中。我的目标是在该区间内选择绝对准确度至少为 1.e-7 的近似值。当然,如果 x 为负值,我们知道 sin(x) 是一个奇函数,所以这是微不足道的。

我注意到 Hart 中的近似值倾向于采用 sin(alphapix) 的形式,其中 x 位于区间 [0,1] 中。如果我随后选择 alpha = 1/2 的近似值,我将得到一个在所选间隔内有效的近似值。因此,对于区间 [0,pi/4] 的近似值,我们寻找 alpha = 1/4。

接下来,我寻找一个绝对准确度至少为 7 位左右的近似值,我更喜欢使用有理多项式近似值,因为它们的效率更高一些。浏览第 118 页上的表格(我的 Hart 副本来自 1978 年),我发现 alpha = 1/4 的近似值符合要求:索引 3060。

这个近似的形式是

sin(alpha*pi*x) = x*P(x^2)/Q(x^2)

所以现在我切换到给出 SIN 3060 系数的页面。在我的副本中,它位于第 199-200 页。有5个系数,P00、P01、P02、Q00、Q01。 (注意这里使用的有点不标准的科学记数法。)因此,P(分子多项式)有 3 项,而分母 Q 有 2 项。写出来,我明白了:

sin(alpha*pi*x) = (52.81860134812 -4.644800481954*x^3 + 0.0867545069521*x^5)/ ...
    (67.250731777791 + x^2)

现在让我们在 MATLAB 中尝试一下。

x = linspace(0,pi/4,10001);
xt = x*4/pi; % transform to [0,1]
sine = @(x) (52.81860134812*x -4.644800481954*x.^3 + ...
     0.0867545069521*x.^5)./(67.250731777791 + x.^2);

max(abs(sin(x) -sine(xt)))
ans =
   1.6424e-09

plot(x,sin(x)- sine(xt),'-')

注意 y 轴上的 1e-9。

看起来这是在该特定区间内对 sin(x) 进行近似的最合理选择,尽管这提供了大约 29 位的准确度,而不是您要求的 23 位。如果您愿意选择不同的范围缩小区间,有一些选择可能会节省一个术语,可能会以您不需要的几位为代价。

log2(max(abs(sin(x) -sine(xt))))
ans =
      -29.182

【讨论】:

  • 对于数字人来说,《哈特》是你读过的最甜蜜的书。它也有许多减少范围的技巧和其他技巧。每次拿起我的副本时,我仍然会微笑,尽管它有点过时了,因为似乎没有人再关心这些事情了。毕竟每一种语言通常都有一套完整的基础函数,三角函数、指数函数等等。
  • 我希望编辑就足够了。正如我所说,如果您像我一样喜欢减速机,那么《哈特》是一本精巧的书。
  • 这只是一个不同的近似值。哪个更好取决于您的鸿沟成本。当然,Hart 也提供了简单的多项式逼近,所以没有什么能阻止您使用其中之一。真正的重点是不要重新创建容易查找的内容,除非这是您想为自己的教育做的事情。
  • 我遇到了可怕的错误。我使用多项式近似(索引 3040)尝试了您的方法。这是代码和结果: x = linspace(0,pi/4,10001); xt = x*4/pi; % 转换为 [0,1] 正弦 = @(x)(0.785398160854 - 0.080745432524 .* xt.^3 + 0.002490001007 .* xt.^5 - 0.000035950439 .* xt.^7); z = sin(x);最大值(abs(正弦(xt)-sin(x)))ans = 0.785398160854
  • 哦,你看到我刚才所做的不同了吗?两个角色能带来多大的不同。 x = linspace(0,pi/4,10001); xt = x*4/pi;正弦 = @(x)(0.785398160854*x - 0.080745432524 .* xt.^3 + 0.002490001007 .* xt.^5 - 0.000035950439 .* xt.^7); z = sin(x);最大值(abs(正弦(xt)-sin(x)))ans = 2.2885e-09 >>
猜你喜欢
  • 1970-01-01
  • 2017-10-18
  • 1970-01-01
  • 2020-10-27
  • 2021-07-18
  • 1970-01-01
  • 2015-10-08
  • 2010-12-25
  • 2019-05-12
相关资源
最近更新 更多