2010-08-03 71 views
2

下面的代码用于计算两个城市之间的英里数。在这种情况下,从雅茅斯,ME到Yarmouth,ME的距离 - 显然为零 - 这意味着雅茅斯X英里范围内的城市的结果应包括雅茅斯本身。SQL Server 2005中的浮点问题

的问题是,雅茅斯的经度和纬度似乎是导致浮点问题的某种(我还没有与其他城市看到了这一点):

DECLARE @fromlong FLOAT, @fromlat FLOAT, @tolong FLOAT, @tolat FLOAT, @test FLOAT 

SET @fromlong = 43.8219 
SET @fromlat = -70.1758 
SET @tolong = 43.8219 
SET @tolat = -70.1758 
SET @test = SIN(@fromlong/(180/PI())) * SIN(@tolong/(180/PI())) + COS(@fromlong/(180/PI())) * COS(@tolong/(180/PI())) * COS(@fromlat/(180/PI()) - @tolat/(180/PI())) 

PRINT @test /*** Displays "1" ***/ 

SELECT 3963.0 * ACOS(@test) /*** Displays "a domain error has occurred" ***/ 

首先,这是一个SQL Server错误?

其次,我能做些什么来解决它?我知道在上面的例子中,我可以为IF @test > 1设置一些逻辑,但是这个例子是从嵌入在web应用程序中的查询提取的(不是我的选择),所以我需要修复查询,即修复计算,而不使用TSQL如果可能,并且不扭曲任何其他返回值。有任何想法吗?

+0

为什么浮动如果你需要确切的价值? – buckbova 2010-08-03 20:54:06

+0

我是否应该执行代码时出错?我没有得到一个只是结果为0. – buckbova 2010-08-03 21:05:33

+0

良好的捕获 - 我回去看看数据库,并意识到我使用的是SSMS 2008,但数据库是2005年。我将相应地更改该帖子。 – gfrizzle 2010-08-03 21:13:08

回答

3

评论的共识似乎是使用FLOAT。我只在示例中使用了FLOAT,因为这是读取纬度/经度的列的数据类型,但似乎是问题的核心。既然不能改变列的数据类型本身,最简单的解决办法是改变所产生的计算,这似乎在所有的情况下,以做工精细的数据类型:

SELECT 3963.0 * ACOS(CONVERT(DECIMAL(10, 6), @test)) 

我意识到离开计算为float可能会导致小的舍入误差,但对于此应用程序来说它们可以接受的很小。谢谢所有评论。