在特定半径内查找邮政编码

6
我发现了一个名为Zip Location的PHP/MySQL脚本,由SaniSoft开发,它很好用,但有一个问题:在某些情况下无法正常工作。
似乎任何小于20英里半径的搜索都会返回与20英里相同数量的邮政编码。我在Google上搜索了很多,但没有结果,想知道是否有人对这种情况有所了解。
我宁愿在购买程序之前解决这个问题,也可以借此学习经验。该数据库是一份包含各个邮政编码及其经纬度的列表。该脚本使用一种方法确定输入的邮政编码周围的距离,并根据其经纬度返回该半径内的邮政编码。
谢谢!!
编辑: 通过使用脚本提供的距离函数,我发现程序给出的邮政编码与我的邮政编码之间的距离为0英里。
重大更新
从研究中发现,该数据库具有重复的经纬度值。在使用Zip Locator时,请注意此事项。虽然PHP可以正常工作,但您需要找到新的邮政编码数据库。我将在以后发布我的发现。
3个回答

10

以下近似距离计算比较简单,但可能会产生10%或更大的距离误差。这些近似计算使用以度数表示的纬度和经度值进行。第一个近似只需要简单的数学函数:

Approximate distance in miles = sqrt(x * x + y * y)

where
      x = 69.1 * (lat2 - lat1)
and   
      y = 53 * (lon2 - lon1)

通过添加余弦函数,您可以提高这个近似距离计算的准确性:

Approximate distance in miles = sqrt(x * x + y * y)

where
      x = 69.1 * (lat2 - lat1)
and   
      y = 69.1 * (lon2 - lon1) * cos(lat1/57.3)
如果您需要更高的精度,必须使用精确的距离计算方法。由于地球是一个球体,所以精确的距离计算需要使用球面几何。此外,精确的距离计算还需要高水平的浮点数学精度——大约15位数字的精度(有时称为“双精度”)。在精确计算中使用的三角函数还需要将纬度和经度值从度转换为弧度。要将纬度或经度从度转换为弧度,请将该数据库中的纬度和经度值除以180/π,即57.2958。假设地球半径为6,371公里,或3,958.75英里。
在计算中必须包含度到弧度的转换。用度替换弧度,计算公式如下:
          Exact distance in miles = 3958.75 * arccos[sin(lat1/57.2958) *
                               sin(lat2/57.2958) + 
                               cos(lat1/57.2958) * 
                               cos(lat2/57.2958) * 
                               cos(lon2/57.2958 - lon1/57.2958)]

1

第二次尝试!

看到您编辑的问题陈述,我会关注您如何分配邮政编码值。

如果您的邮政编码是整数而不是字符串,可能会引入许多错误。最大的问题是美国邮政编码可以以0开头。

ziptest.php中的示例不好,因为它们将邮政编码视为整数。当您尝试使用整数描述我的邮政编码时:

$zip1 = 02446;

PHP将其解释为八进制值2446。phpZipLocator使用该值作为字符串而没有进行任何显式转换。因此,PHP将其作为八进制2446的十进制值(1318)作为字符串给出,这根本不是邮政编码。

phpZipLocator不是通知找不到邮政编码,而是在一个不存在的东西周围的所有邮政编码中进行半径搜索,它决定应该是1。

如果我使用字符串设置邮政编码

$zip1 = '02446';

我得到了正确的结果。

在我看来,phpZipLocator似乎需要一些改进。


非常感谢你,otterfan。给你加1分,但不幸的是这并没有解决问题。我正在使用的邮政编码是11950,半径设置为5,结果出现了73个邮政编码。目前我通过一个POST变量发送邮政编码变量。但是我将变量改为$zip1 = '11950';,结果仍然相同。 - Chris Bier
我看到了它是如何与你的邮政编码配合工作的,这里有一些有趣的东西。 - Chris Bier
更有趣的是,其中一些出现的73个邮政编码距离大约20英里。 - Chris Bier
结果发现,这个数据库中有很多重复的邮政编码经度和纬度。搜索 72.6370 40.92232。该死。 - Chris Bier

0

在 phpZipLocator 的演示脚本(ziptest.php)中,半径的默认值为 20 英里。

$radius = 20;
$zipArray = $zipLoc->inradius($zipOne,$radius);

我猜测你的代码中仍然存在$radius的值,它正在覆盖你想要使用的半径。尝试使用搜索和替换功能来查找$radius

更好的方法是使用调试器查看你的代码,并查看在调用inradius()$radius是否设置为20。


我第一次直接更改了那个值。不过还是谢谢你的帮助。 - Chris Bier
我使用了距离函数,令我惊讶的是出现了离我邮编0英里的邮编。 - Chris Bier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接