Fastest way to calculate the distance between two

2020-06-09 04:26发布

问题:

Distance between two points:

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

Is there a way to do this math faster in objective-C ?

EDIT: I think I need to clarify above. I wrote the formula above just to clarify what formula I am using to calculate the distance. ^ is not meant to represent xor - I just wanted to represent the mathematical formula without using any functions like pow or anything, so I meant to use ^ to "raise to the power off". I was wondering if anyone knows if using bitwise operators, or otherwise writing code in assembly would give an optimized version. I am using the formula in an iPhone / iPad application.

回答1:

No, if you need the exact distance you cannot beat that formula.

Although to be clear ^ is not an operator for squaring a value, but a bit operator that does xor.

you will need something like

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

If you can live with just the square (which is useful when you just want to do something like sort by distance, you can use the much more efficient

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

These will be at least as good as a solution pow. At worst, pow() will use the stack and be less efficient, but maybe your compiler turns it into x*x for this case.



回答2:

Just offering this as a simple, nice looking solution. It is most likely not any faster than any previously given, just shorter. I personally am using hypot.

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

Per the docs, this will return you "The square root of (x^2+y^2)."



回答3:

On an Intel Mac Clang will compile:

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

into a grand total of 6 instructions for the maths: sub, mul, sub, mul, add, sqrt; pretty hard to beat that. (sqrt is a single instruction, though it takes multiple cycles).



回答4:

double dist = sqrt ( pow((x1-x2), 2) + pow((y1-y2), 2) );

considering x1, x2, y1, y2 are float or double or integer.



回答5:

About the only thing that can be improved here is the square root calculation function.

I've tried these two functions (found in a Wikipedia article on square root computation) to calculate approximate square root values:

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;
}

But on my Core 2 Duo Pentium CPU they don't seem to be faster than the x87 FPU FSQRT instruction. See if they work faster than the standard sqrtf()/sqrt() on your platform and if the accuracy is sufficient.