【问题标题】:Efficiently finding the closest zero of an arbitrary function有效地找到任意函数的最接近零
【发布时间】:2020-10-02 22:14:51
【问题描述】:

总之,我试图从给定的x 开始,并在正方向上找到f(x) = 0 的最近点。为简单起见,仅在区间 [initial_x, maximum_x] 中需要解决方案(已给出最大值),但任何更好的范围都是可取的。此外,特定的精度不是强制性的;我希望最大化它,但不以性能为代价。

虽然这看起来很简单,但有一些注意事项会使解决方案变得更加困难。

  1. 性能是第一要务,甚至高于某些精度。需要在对f(x) 的尽可能少的调用中找到零,因为此代码每秒会运行多次。
  2. 不保证此行中包含任何特定数量的零。函数与 x 轴相交的位置可能有 0 个、1 个或多个。 (这就是为什么直接二分查找不起作用的原因。)
  3. 函数f(x) 不能代数操作,只支持离散点的数值计算。 (这就是无法通过分析找到解决方案的原因。)

我目前的策略是定义一个在可接受的精度损失范围内的步长,然后以增量进行测试,直到找到一个保证至少有一个零的区间(在 [a,b] 中,a和 b 在 0) 的对边。从那里,我使用二进制搜索来缩小(更多)确切点。

// assuming y != 0
initial_y = f(x);
while (x < maximum_x) {
  y = f(x);
  // test to see if y has crossed 0
  if (initial_y > 0) {
    if (y < 0) {
      return binary_search(x - step_size, x);
    }
  } else {
    if (y > 0) {
      return binary_search(x - step_size, x);
    }
  }
  x += step_size;
}

这有几个缺点,主要是分辨率和性能之间需要权衡取舍(step_size 越小,效果越好,但需要的时间越长)。我可以采取更有效的公式或策略吗?我想过使用y 的值来缩放步长,但我不知道如何在这样做时保持精度。

解决方案可以是任何语言,因为我更多的是寻找找到零的策略,而不是特定的程序。

(编辑:)

上面的函数假设是连续的。

为了澄清这个问题,我知道这个问题可能无法完全解决。我只是在寻求提高算法速度或精度的方法。我目前使用的那个运行良好,尽管它在许多边缘情况下都失败了。

例如,需要较少步数且精度相似的解决方案,或另一种提高精度或可靠性但对性能有一定影响的算法都将非常有帮助。

【问题讨论】:

  • 你的策略是明智的,但它不能保证你会找到 first 根(即使在给定的容差内),因为你会跳过间隔偶数个根。不知道您通常可以做得更好,至少对目标功能有所了解。考虑一个完全任意函数可能是一个“病态”函数,例如sin(1/x)floor(1/x) mod 10,在您开始的点附近有无数个零。
  • 这就是问题所在。本质上,我正在使用用户创建的函数,所以我不能保证它会以任何特定的方式运行。而且,我明白你在说什么,这就是我寻求改进的原因。当前的实现有很多错误,当函数有很多接近零并且在边缘情况下经常失败。
  • 这是不可能解决的。为了得到一些明智的答案,你需要设置一些限制。

标签: math glsl


【解决方案1】:

在一般情况下,您的问题基本上是不可能解决的。例如,没有算法可以找到sin(1/x)的“第一个”根,从x=0开始。

一个暂定的答案是通过指数搜索,即从一小步开始并按照几何级数而不是算术级数增加它,直到找到符号的变化。但是,如果第一个根比初始步骤更近,或者如果第一个根后面跟着一个接近的根,这将失败。

如果没有关于f 行为的任何信息,我什至不会尝试任何东西(但“标准”根查找器),这太绝望了! (但我相信你确实掌握了一些信息。)

【讨论】:

  • 我不太明白指数搜索有什么帮助。它不是越接近答案就会降低精度,从而降低最终答案的可靠性和精度吗?关于f 的行为,我无法进一步缩小范围,因为它是用户定义的。但是,我可以说它表示代入 3D 表面的线的参数方程。链接到我当前的实现是否有帮助?
  • @KiranWells:我对此的最后一句话:“如果没有关于f 行为的任何信息,我什至不会尝试任何东西(除了“标准”根查找器),这太绝望了! "
猜你喜欢
  • 2016-09-30
  • 2012-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多