Hello everyone, I'd like to first apologize for the length of this post -- I'm really confused and I'm not even sure if I make any sense in it. Hopefully, somebody can make sense of this to help me, and I'd greatly appreciate it! I have what I would think would be a relatively simple problem to solve, however, I don't know how to go about solving it. At the most simplistic, what I need is a way, given a single ZIP code, to search for everything within a given radius of it. For example, the types of questions I want to be able to answer are "What ZIP codes are within a 20 mile radius of ZIP 30034?" Now, I've done some looking up, and the more and more I look things up on this subject, the more and more perplexed I become. Allow me to state first, that math /definitely/ isn't my strong point, and that might be why I'm not "grasping" it. What I do know is that each ZIP code "maps" to a latitude/longitude. I also know that there are a number of formulas out there that can compute the distance between (latitude 1, longitude 1) and (latitude 2, longitude 2). It seems that the Haversine formula is the most discussed and reasonably accurate, so it seems to be a reasonable choice for working with this data. The alternatives are all seemingly exponentially over my head, in addition, and this one I've been beating my head on the desk over for a couple of days now, anyway. What I don't know is: * How to compute distance using the Haversine formula. I was on a site that tries to explain such things, and where it would get a result of 884.2 km (about correct) for two points I entered, the only result I can manage to get out of the formula by "hand" (using GNU bc) is 11,148.534.... somethings, presumably kilometers, which I know is not correct. * How to understand the Haversine formula -- That's really important to me, to understand how it works before I try using it extensively. The point is going to be to implement it into a program, nonetheless, I'd like to understand it and how it works before I write it into the program. It probably does not help that I haven't the foggiest about what things like atan2, sin, and cos actually *do*. * How to determine what the input really is. The coordinates that I have access to are in decimal, e.g.: mysql> SELECT * FROM dataZipCode WHERE zipcode='43609'; +---------+-------------+--------------+--------+-------+------+ | zipcode | latitude | longitude | city | state | abbr | +---------+-------------+--------------+--------+-------+------+ | 43609 | +41.6247490 | -083.5842340 | TOLEDO | OHIO | OH | +---------+-------------+--------------+--------+-------+------+ 1 row in set (0.00 sec) From what I'm reading, I see lots of discussion of "radians" and the like. Is that what these latitudes/longitudes are expressed in? * How to determine what the output should be. Everywhere I see km in use. I'm in the U.S., where we like to be very different from everywhere else and use miles. How retarded is that? Well, anyway, I can convert from miles <--> km without a problem as that is relatively easy. What I don't know is if any actual other adjustments need to be made to account for miles vs. km in the formula itself. * The formula that I have is as follows. I'm not sure if all the special characters will show up or not, so I've pasted it as well as rewritten as I understand it in plaintext. R = earthâ€™s radius (mean radius = 6,371km) Î”lat = lat2 âˆ’ lat1 Î”long = long2 âˆ’ long1 a = sinÂ²(Î”lat/2) + cos(lat1).cos(lat2).sinÂ²(Î”long/2) c = 2.atan2(âˆša, âˆš(1âˆ’a)) d = R.c R = earth's radius (6371 km) d_lat = lat2 - lat1 d_long = long2 - long1 a = sin(d_lat/2)^2 + cos(lat1)*cos(lat2)*sin(d_long/2)^2 c = 2*atan2(sqrt(a), sqrt(1-a)) d = R*c Now, as I understand things, this means that given: mysql> SELECT * FROM dataZipCode WHERE zipcode='30034' OR zipcode='43609'; +---------+-------------+--------------+---------+---------+------+ | zipcode | latitude | longitude | city | state | abbr | +---------+-------------+--------------+---------+---------+------+ | 30034 | +33.6907570 | -084.2511710 | DECATUR | GEORGIA | GA | | 43609 | +41.6247490 | -083.5842340 | TOLEDO | OHIO | OH | +---------+-------------+--------------+---------+---------+------+ 2 rows in set (0.00 sec) mysql> I, according to the few places I've been, should get something around 884.2 km (549.4 mi) as a result. However, I actually get (this is from GNU bc, which is the best calculator I have access to right now): ======================================== lat1 = 33.6907570 long1 = -084.2511710 lat2 = 41.6247490 long2 = -083.5842340 d_lat = lat2-lat1 d_long = long2-long1 a = s(d_lat/2)^2 + c(lat1)*c(lat2)*s(d_long/2)^2 c = 2*(a(sqrt(a)/sqrt(1-a))) d = 6371*c d 11148.53419822366947556742 ======================================== .... which does not appear to be correct. AFAIK, bc doesn't have atan2, but I read somewhere that a (which in bc is atan) works as long as you divide y by x instead of writing (y,x). However, the result is still just as invalid if I flip y and x, yielding: ======================================== d 8866.55259779690324653382 ======================================== At the end of all of this, what I really need to know is what am I doing wrong in the formula, and if there is a mathematical way to find every valid latitude/longitude pair given a radius from the starting point so that I can just get the ranges and find the ZIP codes that are associated with them? I apologize for the probably excess verbosity. I really am confused here, and I just don't know what to make of it all. It's probably pretty obvious that I stink at this level of mathematics. Thanks in advance for any help, Mike

You need to convert latitude and longitude to radians (they're given in degrees) because your trig functions require radians. Here's a Python version. 884.16235845575545 Note that this calculation does not take into account that the Earth is not a perfect sphere. Hopefully, its good enough for your purposes.

I don't know what you mean by "everything within a given radius of it." The points you have are most likely the long. and lat. for the PO itself. I live about a mile away from my PO. and my long. & lat. would be different. There is another PO NE of me and another SW. (Each about 2 miles away.) You can't tell which zip code a given house is in without knowing the zip code boundries. However, you can tell whether POs themselves are within x miles of each other. Also, there is something called spherical geomatry which assumes the earth is round, not flat, and that can be important if distances are large. Bill

Thank you for the reply. I've managed to tackle this formula, I think. I've got a UNIX bc function written that manages it quite nicely both finding the distance between point A and B, and giving me points to use as a box containing lots of addresses. Running manual SQL queries against my database with the resulting output gives me the data that I'm looking for now. Now my only leftover problem is that I'm having a hard time getting the same formulas to work in PHP. That, however, is another topic for another place. Since I'm only working with segments of no more then 400 sq. miles, I don't think that the fact that the shape of the Earth is not a perfect sphere is going to cause me a problem for that small of a distance - though if I am wrong, please correct me. Thank you for your help! Take care, Mike