【问题标题】:Fast, inaccurate sin function without lookup没有查找的快速、不准确的 sin 函数
【发布时间】:2011-08-23 15:26:41
【问题描述】:

对于海洋着色器,我需要一个快速函数来计算 sin(x) 的近似值。唯一的要求是它是周期性的,并且大致类似于正弦波。

泰勒级数太慢了,因为我需要计算 x 的 9 次方才能得到一个完整的周期。

有什么建议吗?

编辑:对不起,我没有提到,我不能使用查找表,因为它在顶点着色器上。查找表将涉及纹理样本,它在顶点着色器上比内置的 sin 函数慢。 它不必以任何方式准确,只要看起来不错。

【问题讨论】:

  • 泰勒级数对于 0 到 π/2 之间的 x 是否慢?如果可以接受,那么您可以使用 sin 的对称性来计算其他值。

标签: math trigonometry shader


【解决方案1】:

对尽可能多的术语使用Chebyshev 近似值。如果您的输入角度被限制为表现良好(-π .. +π 或 0 .. 2π),这将特别容易,因此您不必首先将参数减少到合理的值。您可以使用 2 或 3 个术语而不是 9 个。

【讨论】:

  • +1 切比雪夫,这是最好的方法。但是,如果可能的话,减少射程是一个巨大的优势。
【解决方案2】:

您可以为某些值创建一个带有 sin 值的查找表,并在这些值之间使用线性插值。

【讨论】:

  • @super 标题已编辑。你甚至读过编辑/历史吗?:)
  • 这个答案的历史怎么样
【解决方案3】:

sin(x) 的有理代数函数逼近,从 0 到 π/2 有效:

f = (C1 * x) / (C2 * x^2 + 1.) 

使用常量:

c1 =   1.043406062 
c2 =  .2508691922 

这些常数是通过最小二乘曲线拟合找到的。 (使用子程序 DHFTI,由 Lawson & Hanson 编写)。

如果输入在 [0, 2π] 之外,则需要取 x mod 2 π。
要处理负数,您需要编写如下内容:

t = MOD(t, twopi)
IF (t < 0.) t = t + twopi

然后,要将范围扩展到 0 到 2π,请使用以下内容减少输入:

IF (t  < pi) THEN
  IF (t < pi/2) THEN
    x = t
  ELSE
      x = pi - t
   END IF
 ELSE 
   IF (t < 1.5 * pi) THEN
     x = t - pi
  ELSE
     x = twopi - t
   END IF
END IF

然后计算:

f = (C1 * x) / (C2 * x*x + 1.0)
IF (t > pi) f = -f

结果应该在真正正弦的 5% 以内。

【讨论】:

  • 我已经编辑了我的答案以回应这些批评。澄清一下,有理函数 f = (c1 * x) / (c2 * x^2 + 1) 在 0 到 π/2 之间是有效的。减少 IF 块将其扩展到 0 到 2π,但您必须事先这样做。你必须先取 mod 2π。 Lawson 和 Hanson 编写了一个有助于查找常数的最小二乘子程序,任何最小二乘程序都可以达到目的。如果你能把13行修正码压缩成一行,给我看看。
  • Optimized for relative error 而不是绝对错误:float sin_rational (float a) { return (1.01815748f * a) / (0.23133484f * a * a + 1.0f); }
  • 安迪,我收回了我的反对票,因为我很欣赏你的回应。剩下的我会在我有空的时候再回复你。
  • 我很抱歉,如果实施得当,该功能确实可以工作,而我最初没有这样做。但是,我的基准测试表明它比在现代 PC 上运行的 Java 内置 Math.sin() 函数慢得多,我的测试表明它的精确度明显低于另一种方法(参见stackoverflow.com/a/28050328/773113)也恰好比Java的内置函数快得多。
【解决方案4】:

嗯,你没有说你需要它有多准确。正弦可以用斜率 2/pi 和 -2/pi 在区间 [0, pi/2], [pi/2, 3*pi/2], [3*pi/2, 2*pi ]。在减小角度 mod 2*pi 后,可以通过乘法和加法来获得这种近似值。

【讨论】:

  • 嗯,比这更准确:P 从这个意义上说,它不需要“准确”,我不关心找到给定角度的近似正弦。我只是想找到看起来像波浪的平滑函数。
  • @Hannesh:哈,好吧,至少我没说它可以用函数 f(x) = 0 来近似。
【解决方案5】:

使用查找表可能是控制速度和准确性之间权衡的最佳方式。

【讨论】:

  • -1 因为我想这在今天是不正确的,尤其是当未来时钟频率会更高时
猜你喜欢
  • 2015-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 2012-10-29
  • 2020-06-06
相关资源
最近更新 更多