locked
Calculating distance between two points RRS feed

  • Question

  • My code:

    (Math.Sqrt(Math.Abs(x1 - x2) ^ 2 + Math.Abs(y1 - y2) ^ 2 + Math.Abs(z1 - z2) ^ 2))

    Should calculate the distance between (x1,y1,z1) and (x2,y2,z2). It does, kinda, though the result is a pretty small number AND a weird number. If the distance should be bigger then another, it isn't. It's just not doing it's job. Also I expect numbers around 1000 with the large numbers I'm working with, though it returns numbers around 30 with is way too low.

     

    What's wrong with this? I think it's easy though I can't find it.

     

    Thanks,

    ~ Eggmaker.

    Monday, August 30, 2010 5:36 PM

Answers

  • You should try this:

    (Math.Sqrt(Math.Pow(Math.Abs(x1 - x2), 2) + Math.Pow(Math.Abs(y1 - y2), 2) + Math.Pow(Math.Abs(z1 - z2), 2)));

     

    In C#, the ^ operator is for XOR and not for power.

     

    Regards.

     

    • Marked as answer by _Yoshi_ Monday, August 30, 2010 6:11 PM
    Monday, August 30, 2010 6:06 PM

All replies

  • What are your inputs and outputs?  Also, strictly speaking, you don't need the abs function -- squaring a negative value will result ina positive number anyway. 


    Michael Asher
    Monday, August 30, 2010 5:52 PM
  • The code has completely different meaning in VB and C#.  I think you want VB.  If you really are using C#, replace the exclusive Or operator with a multiplication:  (X1 - X2) * (X1 - X2).

    Monday, August 30, 2010 5:56 PM
  • If I don't add the 'abs' function, I get NaN as result..

     

    Sample result:

     

    x1: 17303

    x2: 16913

    y1: 450

    y2: 500

    z1: 18302

    z2: 19087

    Result: 25,9807621135332


    Monday, August 30, 2010 5:59 PM
  • @

    The code has completely different meaning in VB and C#.  I think you want VB.  If you really are using C#, replace the exclusive Or operator with a multiplication:  (X1 - X2) * (X1 - X2).

     

    Yes, I'm using C#. The last part I don't understand, could you explain that better please?

    Monday, August 30, 2010 6:04 PM
  • You should try this:

    (Math.Sqrt(Math.Pow(Math.Abs(x1 - x2), 2) + Math.Pow(Math.Abs(y1 - y2), 2) + Math.Pow(Math.Abs(z1 - z2), 2)));

     

    In C#, the ^ operator is for XOR and not for power.

     

    Regards.

     

    • Marked as answer by _Yoshi_ Monday, August 30, 2010 6:11 PM
    Monday, August 30, 2010 6:06 PM
  • Thanks alot, didn't know that.
    Monday, August 30, 2010 6:11 PM
  • Yes, I'm using C#. The last part I don't understand, could you explain that better please?


    The code you posted is VB code for distance.  The equivalent C# code is:

          Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));

    Monday, August 30, 2010 6:16 PM
  • I saw that in a previous post, thanks for clearing it up.
    Monday, August 30, 2010 6:22 PM
  • I disagree.  You shouldn't use Pow with an exponent of 2.  Use x * x instead of Pow(x,2)

    var dx = x2 - x1;

    var dy = y2 - y1;

    var dz = z2 - z1;

    var distance_squared = dx * dx + dy * dy + dz * dz;

    /* this quantity (distance_squared) is faster to calculate than distance (no sqrt) and is still good for lots of things.  Like comparing distances: distance_squared1 < distance_squared2 if-and-only-if distance1 < distance2.  And it's good for sorting too.

     One of my favourites is when you are testing collision with a circle/sphere.  The temptation is to find out if distance < radius.  But instead you should check if distance_squared < radius*radius  (and radius*radius is likely a constant, and can be computed once into a radius_squared) */

    var distance = Math.Sqrt(distance_squared); // this is the most expensive part of the computation.

     

    Monday, August 30, 2010 7:07 PM
  • I disagree.  You shouldn't use Pow with an exponent of 2.  Use x * x instead of Pow(x,2)

    var dx = x2 - x1;

    var dy = y2 - y1;

    var dz = z2 - z1;

    var distance_squared = dx * dx + dy * dy + dz * dz;

    /* this quantity (distance_squared) is faster to calculate than distance (no sqrt) and is still good for lots of things.  Like comparing distances: distance_squared1 < distance_squared2 if-and-only-if distance1 < distance2.  And it's good for sorting too.

     One of my favourites is when you are testing collision with a circle/sphere.  The temptation is to find out if distance < radius.  But instead you should check if distance_squared < radius*radius  (and radius*radius is likely a constant, and can be computed once into a radius_squared) */

    var distance = Math.Sqrt(distance_squared); // this is the most expensive part of the computation.

     


    What does this have to do with anything?  You're trying to micromanage managed code.  It's counterproductive.
    Monday, August 30, 2010 7:19 PM
  • What does this have to do with anything?  You're trying to micromanage managed code.  It's counterproductive.

    Err, you can claim his response is off topic, but the approach certainly isn't counterproductive.  In C#, a multiply is over 20X faster than a Pow invocation .. and that speed difference is nothing compared to what you can gain by working with the square directly, avoiding the square root.  Of course, the latter approach isn't always possible, but you should never use Pow for a squaring except for one-off results.
    Monday, August 30, 2010 7:29 PM
  • It's that you know I don't use the check 'that' often and speed isn't very important here. It's just important that it's done.
    Monday, August 30, 2010 7:31 PM
  • What does this have to do with anything?  You're trying to micromanage managed code.  It's counterproductive.

    Err, you can claim his response is off topic, but the approach certainly isn't counterproductive.  In C#, a multiply is over 20X faster than a Pow invocation .. and that speed difference is nothing compared to what you can gain by working with the square directly, avoiding the square root.  Of course, the latter approach isn't always possible, but you should never use Pow for a squaring except for one-off results.

    It's counterproductive, because while you're thinking about triva you could be programming the next module of the program.  I noticed you get your statistics the same place I get mine.
    Monday, August 30, 2010 7:56 PM
  • It's counterproductive, because while you're thinking about triva you could be programming the next module of the program. 

    Or you could be on the phone with your boss, trying to explain why your software runs so much slower than your competitor's.  :)    

    Sure, there's always a trade-off between time spent optimization and coding, but there's really no excuse for things like using Pow to square a value -- writing x*x doesn't take any more time than Pow(x,2).

    Monday, August 30, 2010 8:45 PM
  • Or you could be on the phone with your boss, trying to explain why your software runs so much slower than your competitor's.  :)    

    Just tell him it's because you're trying to micromange managed code and they're using native code.  They will always have the advantage in performance.  But you should have the advantage in user interaction and proliferation of features.  You get that by seeing the forest, not the trees.
    Monday, August 30, 2010 9:11 PM
  • Perhaps you can explain to me how typing Pow(x,2) instead of x*x is going to give you a major advantage in "user interaction and proliferation of features" ... especially when the worse-performing version actually takes a few milliseconds longer to type out than the faster one.   It's not micromanagement to use the proper function for the job.  This isn't any different than a programmer typing  sin(x)/cos(x) instead of simply using tan(x).
    Monday, August 30, 2010 9:24 PM
  • Perhaps you can explain to me how typing Pow(x,2) instead of x*x is going to give you a major advantage in "user interaction and proliferation of features" ... especially when the worse-performing version actually takes a few milliseconds longer to type out than the faster one.   It's not micromanagement to use the proper function for the job.  This isn't any different than a programmer typing  sin(x)/cos(x) instead of simply using tan(x).

    It's the mind set.  Your thinking native coding on ancient processors instead of managed coding on current processors.
    Monday, August 30, 2010 9:48 PM
  • It's the mind set.  Your thinking native coding on ancient processors instead of managed coding on current processors.

    Lol, what?  Multiplication is now only for "ancient processors"?  Believe it or not, x*x is still managed code, even if you don't call a library function to perform it.   The mind set here is writing efficient code vs. the "I don't care -- if its slow, it must be the computer's fault" attitude.

     

    Monday, August 30, 2010 9:58 PM
  • I tried a different source other than the dark orifice for statistics.  Math.Sqrt adds little time to the calculation.  My thinking about the capabilities of the .NET framework to deal with integral powers for Math.Pow was incorrect.  I thought ^2 would be replaced with a multiply.  No.  Math.Pow( x, 2) increases the overall calculation by 10 times.  I still like the VB x^2 for clarity.  (no one eats crow without a parting shot.)
    Thursday, September 2, 2010 9:18 PM
  • no one eats crow without a parting shot.

    Lol, well the wise man only has to taste that dish once, then he learns from it and moves on.  Those that refuse have it rubbed in their face over and over.  I salute you.

    I am curious though about your source for the Sqrt claim. It should be faster than a Pow call (its not a transcendental after all), but compared to the two-multiplies-and-an-add the basic calculation entails, it should slow things by a large multiple.  I don't want to show my age, but the last time I speed tested such code, though, was on an 8-bit CPU.  

     

     

    Thursday, September 2, 2010 10:24 PM
  • no one eats crow without a parting shot.

    Lol, well the wise man only has to taste that dish once, then he learns from it and moves on.  Those that refuse have it rubbed in their face over and over.  I salute you.

    I am curious though about your source for the Sqrt claim. It should be faster than a Pow call (its not a transcendental after all), but compared to the two-multiplies-and-an-add the basic calculation entails, it should slow things by a large multiple.  I don't want to show my age, but the last time I speed tested such code, though, was on an 8-bit CPU.

    I timed the methods in a 999999 loop.  Baseline was about 30 ms, with Sqrt about 40 ms and with Pow about 300 ms.
    Thursday, September 2, 2010 10:30 PM
  • I tried a different source other than the dark orifice for statistics.  Math.Sqrt adds little time to the calculation.  My thinking about the capabilities of the .NET framework to deal with integral powers for Math.Pow was incorrect.  I thought ^2 would be replaced with a multiply.  No.  Math.Pow( x, 2) increases the overall calculation by 10 times.  I still like the VB x^2 for clarity.  (no one eats crow without a parting shot.)

    Premature optimization is not a good idea, but just because the OP doesn't want an optimal solution doesn't mean that other readers of this post won't want it.  I was trying to be helpful.

    A good technique to calculate the magnitude of a vector is to make use of the inner product (a.k.a. dot product)  If you take the inner product of a vector and itself, you get a scalar that is the product of the vector's magnitude and itself.  

    The savvy developer should be making use of a vector class.  This vector class should have an inner product function, and to get the magnitude of a vector, you would take the square root of the inner product of the vector with itself.

    The math goes like this:

    A dot B = length(A) * length(B) * cos(angle_between_A_and_B)

    A dot A = length(A) * length(A) * cos(zero)

    A dot A = length(A) * length(A) * 1

    length(A) = sqrt(A dot A)


    The code for the inner product would likely be written as A.x * B.x + A.y * B.y.  Notice how there can be no pow(foo, 2) here because A and B are different?  So the clarity for me, in this case, came from the original dx * dx of the inner product as opposed to pow(dx,2).  

    Mathematically, for real numbers they are equal, of course, so it's hard to dispute which is better because they will give the same answer.  Any real compelling reason to use one over the other should come from performance, or maintainability of the code.  

    We've established that performance is better for x * x, but if we are considering the maintainability of the code, then there should be a proper vector library being used for the points.  x1 and y1 should be a vector v1.  and x2 and y2 should be a vector v2.  length(v) := sqrt(innerproduct(v,v)).  and innerproduct(a,b) := a.x * b.x + a.y * b.y.  One could even argue that there should simply be distance_between_points function distance(v1,v2) := (v2-v1).length()

    There you go!  I've started your linear algebra library for you.  :)  Next you can add transformation matrices. ;)

     

    Friday, September 3, 2010 5:07 PM
  • Math.Abs() is redundant here.  The square of any number is positive.
    Monday, December 21, 2015 7:03 PM