【问题标题】:Fastest way to calculate the distance between two CGPoints?计算两个CGPoints之间距离的最快方法?
【发布时间】:2012-02-02 06:44:21
【问题描述】:

两点之间的距离:

sqrt((x1-x2)^2 + (y1-y2)^2)

有没有办法在 Objective-C 中更快地完成这个数学运算?

编辑:我想我需要在上面澄清一下。我写了上面的公式只是为了澄清我用来计算距离的公式。 ^ 并不是要代表 xor - 我只是想代表数学公式而不使用任何函数,如 pow 或任何东西,所以我打算使用 ^ 来“提高电源关闭”。我想知道是否有人知道使用按位运算符或在汇编中编写代码是否会提供优化版本。我在 iPhone / iPad 应用程序中使用该公式。

【问题讨论】:

  • 我只是想知道是否有人知道执行此类计算的最快方法。通常我只会写出公式并使用 pow 或其他东西,但我不知道使用 * 或按位运算符是否会产生更快的结果。

标签: objective-c math optimization euclidean-distance


【解决方案1】:

不,如果您需要确切的距离,您无法击败该公式。

虽然要明确 ^ 不是求平方的运算符,而是进行异或的位运算符。

你需要类似的东西

double dx = (x2-x1);
double dy = (y2-y1);
double dist = sqrt(dx*dx + dy*dy);

如果您可以只使用正方形(这在您只想执行诸如按距离排序之类的操作时很有用,则可以使用效率更高的方法

double dx = (x2-x1);
double dy = (y2-y1);
double dist = dx*dx + dy*dy;

这些至少与解决方案战俘一样好。在最坏的情况下, pow() 将使用堆栈并且效率较低,但是对于这种情况,您的编译器可能会将其转换为 x*x。

【讨论】:

  • +1 你可以肯定pow 至少会比* 长一个数量级,而且我不认为编译器可以优化pow,因为它不知道可以肯定的是,它并没有被一个完全不同的函数所取代,称为 pow
  • 另外,hypot(dx, dy)
【解决方案2】:

只是将其作为一个简单、美观的解决方案提供。它很可能不会比以前给出的任何更快,只是更短。我个人使用的是hypot

double dist = hypot((x1-x2), (y1-y2));

根据docs,这将返回“(x^2+y^2) 的平方根。”

【讨论】:

    【解决方案3】:

    在 Intel Mac 上 Clang 将编译:

    double distance = ({double d1 = x1 - x2, d2 = y1 - y2; sqrt(d1 * d1 + d2 * d2); });
    

    总共有 6 条数学指令:sub、mul、sub、mul、add、sqrt;很难打败它。 (sqrt 是一条指令,虽然它需要多个周期)。

    【讨论】:

      【解决方案4】:
      double dist = sqrt ( pow((x1-x2), 2) + pow((y1-y2), 2) );
      

      考虑到x1, x2, y1, y2floatdouble 或整数。

      【讨论】:

      • 我认为计算平方的通用幂函数 (pow) 不会比简单的乘法更快。
      【解决方案5】:

      关于这里唯一可以改进的就是平方根计算函数。

      我已经尝试了这两个函数(在 Wikipedia article on square root computation 中找到)来计算近似平方根值:

      float fsqrt(float x)
      {
        float xhalf = 0.5f * x;
        union
        {
          float x;
          int i;
        } u;
      
        u.x = x;
        u.i = 0x5f3759df - (u.i >> 1);
        x *= u.x * (1.5f - xhalf * u.x * u.x);
      
        return x;
      }
      
      float fsqrt2(float z)
      {
          union
          {
              int tmp;
              float f;
          } u;
      
          u.f = z;
      
          /*
           * To justify the following code, prove that
           *
           * ((((val_int / 2^m) - b) / 2) + b) * 2^m = ((val_int - 2^m) / 2) + ((b + 1) / 2) * 2^m)
           *
           * where
           *
           * val_int = u.tmp
           * b = exponent bias
           * m = number of mantissa bits
           *
           * .
           */
      
          u.tmp -= 1 << 23; /* Subtract 2^m. */
          u.tmp >>= 1; /* Divide by 2. */
          u.tmp += 1 << 29; /* Add ((b + 1) / 2) * 2^m. */
      
          return u.f;
      }
      

      但在我的 Core 2 Duo Pentium CPU 上,它们似乎并不比 x87 FPU FSQRT 指令快。看看它们是否比您平台上的标准sqrtf()/sqrt() 工作得更快,以及准确性是否足够。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多