为什么这个MySQL存储函数给出的结果与在查询中进行计算的结果不同?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了为什么这个MySQL存储函数给出的结果与在查询中进行计算的结果不同?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3299字,纯文字阅读大概需要5分钟。
内容图文
这是一个关于使用半正公式计算地球上两个纬度和经度点之间距离的问题,用于需要“找到最近”函数的项目.
在this post中,在MySQL中很好地讨论并解决了hasrsine公式.
然后我询问this question将其转换为存储函数,以便它可用于将来的项目,而无需查找,记住或重新键入长形式的公式.
都很好.除了我的函数结果(稍微)不同于直接在查询中键入公式,所有其他条件相同.为什么是这样?
所以这是我写的函数:
DELIMITER $$
DROP FUNCTION IF EXISTS haversine $$
CREATE FUNCTION `haversine`
(fromLatitude FLOAT,
fromLongitude FLOAT,
toLatitude FLOAT,
toLongitude FLOAT,
unit VARCHAR(20)
)
RETURNS FLOAT
DETERMINISTIC
COMMENT 'Returns the distance on the Earth between two known points of longitude and latitude'
BEGIN
DECLARE radius FLOAT;
DECLARE distance FLOAT;
IF unit = 'MILES' THEN SET radius = '3959';
ELSEIF (unit = 'NAUTICAL_MILES' OR unit='NM') THEN SET radius = '3440.27694';
ELSEIF (unit = 'YARDS' OR unit='YD') THEN SET radius = '6967840';
ELSEIF (unit = 'FEET' OR unit='FT') THEN SET radius = '20903520';
ELSEIF (unit = 'KILOMETRES' OR unit='KILOMETERS' OR unit='KM') THEN SET radius = '6371.3929';
ELSEIF (unit = 'METRES' OR UNIT='METERS' OR unit='M') THEN SET radius = '6371392.9';
ELSE SET radius = '3959'; /* default to miles */
END IF;
SET distance = (radius * ACOS(COS(RADIANS(fromLatitude)) * COS(RADIANS(toLatitude)) * COS(RADIANS(toLongitude) - RADIANS(fromLongitude)) + SIN(RADIANS(fromLatitude)) * SIN(RADIANS(toLatitude))));
RETURN distance;
END$$
DELIMITER ;
这里有一组测试查询,用于查找伦敦眼和白金汉宫之间的距离,仅供参考.显然,通常情况下,您可以使用您要与之比较的地理位置“事物”数据库中的字段替换目的地.
SET @milesModifier = 3959;
SET @myLat = 51.503228;
SET @myLong = -0.119703;
SET @destLat = 51.501267;
SET @destLong = -0.142697;
SELECT @kilometerModifier AS radius,
@myLat AS myLat,
@myLong AS myLong,
@destLat AS destLat,
@destLong AS destLong,
(@milesModifier * ACOS(COS(RADIANS(@myLat)) * COS(RADIANS(@destLat)) * COS(RADIANS(@destLong) - RADIANS(@myLong)) + SIN(RADIANS(@myLat)) * SIN(RADIANS(@destLat)))) AS longFormat,
haversine(@myLat,@myLong,@destLat,@destLong,'MILES') AS distanceMiles,
haversine(@myLat,@myLong,@destLat,@destLong,'NAUTICAL_MILES') AS distanceNautical,
haversine(@myLat,@myLong,@destLat,@destLong,'KM') AS distanceKm,
haversine(@myLat,@myLong,@destLat,@destLong,'METRES') AS distanceMetres,
haversine(@myLat,@myLong,@destLat,@destLong,'YARDS') AS distanceYards,
haversine(@myLat,@myLong,@destLat,@destLong,'FEET') AS distanceFeet,
haversine(@myLat,@myLong,@destLat,@destLong,'') AS distanceDefault
在这个例子中,我们使用里程 – 所以我们将半径(测试中的@milesModifier,函数中的半径)设置为3959.
我得到的结果很有趣(在MySQL 5.2.6社区版上),重点是:
| longFormat | distanceMiles |
|------------------|-----------------|
| 0.99826000106148 | 0.9982578754425 |
longFormat是在查询中完成的数学运算,distanceMiles是函数的结果.
结果是不同的…好吧,所以它在项目中使用函数的意义不大,但我很想知道函数内部或外部的相同公式有不同的结果.
我猜它与FLOAT的长度有关 – 它们没有在函数中指定,我已经尝试指定它们(直到30,15)为我拥有的所有数字和输出提供足够的空间我期待 – 但结果仍然略有不同.
解决方法:
FLOAT是近似数据类型 – 请参阅:
Problems with Floating-Point Values
Numeric Types
尝试将FLOAT更改为DECIMAL(30,15)以确保您具有正确的精度.
如果您想深入讨论浮点,可以尝试这篇文章:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
内容总结
以上是互联网集市为您收集整理的为什么这个MySQL存储函数给出的结果与在查询中进行计算的结果不同?全部内容,希望文章能够帮你解决为什么这个MySQL存储函数给出的结果与在查询中进行计算的结果不同?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。