# ZIP Codes, Latitude/Longitude, lack of understanding.

Discussion in 'General Math' started by Michael Trausch, Mar 2, 2006.

1. ### Michael TrauschGuest

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

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.

Î”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

Michael Trausch, Mar 2, 2006

2. ### mensanatorGuest

You need to convert latitude and longitude to radians (they're given

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.

mensanator, Mar 2, 2006

3. ### BillGuest

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

Bill, Mar 3, 2006
4. ### Michael TrauschGuest

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.