ACOS函數的SQL 2012 bug。

[英]SQL 2012 bug for the ACOS function


I run into this bug in SQL Server 2012 ACOS function:

我在SQL Server 2012 ACOS函數中遇到了這個bug:

declare @lat1 decimal(12,10), @lon1 decimal(12,10), @lat2 decimal(12,10), @lon2 decimal(12,10)
declare @dist float

select @lat1=51.1790825000, @lon1= 4.1590020000, @lat2= 51.1790825000, @lon2= 4.1590020000  
set @dist = SIN(RADIANS(@lat1)) * SIN(RADIANS(@lat2)) + COS(RADIANS(@lat1)) * COS(RADIANS(@lat2)) * COS(RADIANS(@lon1 - @lon2))

print @dist
print ACOS(1)
print ACOS(@dist)

The last print function gives an "An invalid floating point operation occurred." This works fine in SQL Server 2008

最后一個打印函數給出了“一個無效的浮點操作發生”。這在SQL Server 2008中運行良好

Vlad

弗拉德

4 个解决方案

#1


3  

It looks like you're trying to calculate the distance between two points on the Earth. Make your life easier and use the built-in geography type.

看起來你是在計算地球上兩點之間的距離。讓你的生活更輕松,使用內置的地理類型。

DECLARE @lat1 DECIMAL(12, 10) ,
    @lon1 DECIMAL(12, 10) ,
    @lat2 DECIMAL(12, 10) ,
    @lon2 DECIMAL(12, 10)
DECLARE @dist FLOAT

SELECT  @lat1 = 51.1790825000 ,
        @lon1 = 4.1590020000 ,
        @lat2 = 51.1790825000 ,
        @lon2 = 4.1590020000

DECLARE @p1 GEOGRAPHY = GEOGRAPHY::Point(@lat1, @lon1, 4326) ,
    @p2 GEOGRAPHY = GEOGRAPHY::Point(@lat2, @lon2, 4326)

SELECT  @dist = @p1.STDistance(@p2)

#2


1  

Use

使用

print ACOS(CASE WHEN @dist > 1 THEN 1 ELSE @dist END)

@dist is a float datatype and is actually slightly more than 1 due to rounding issues as can be seen from below.

@dist是一個浮點數據類型,由於如下所示的舍入問題,它實際上略大於1。

SELECT CAST(@dist AS BINARY(8)) AS [@dist], 
       CAST(CAST(1 AS FLOAT) AS BINARY(8)) AS [1]

Returns

返回

@dist              1
------------------ ------------------
0x010000000000F03F 0x000000000000F03F

Plugging 010000000000F03F into the IEEE converter here shows that this is approximately 1.0000000000000002220446049250313080847263 which can be verified from the below (returns Y)

將010000000000F03F插入到這里的IEEE轉換器中顯示,這大約是1。00000000000000000000000000000002220446049250313080847263,可以從下面驗證(返回Y)

SELECT 
     CASE WHEN @dist between 1.0000000000000002220446049250313080847 AND 
                             1.0000000000000002220446049250313080848 
     THEN 'Y' ELSE 'N' END

#3


1  

The float value argument for acos() function has to be between -1 to 1 range.. Hence

acos()函數的浮點值參數必須在-1到1之間。因此

FUNCTION [dbo].[Calculate_Distance]  
(  
@Lat1 float, @Long1 float, @Lat2 float, @Long2 float  
)  
RETURNS float  
AS  
BEGIN  

    DECLARE @acosValue float     
    DECLARE @R float  
    SET @R = 3958.7558657440545 -- mi       
    DECLARE @Distance float  
    Set @acosValue= cos( radians(@Lat1) ) * cos( radians( @Lat2 ) ) * cos( radians( @Long2 ) - radians(@Long1) ) + sin( radians(@Lat1) ) * sin( radians( @Lat2 ) ) ;
    IF @acosValue>1.0 
    Begin
    Set @acosValue=1.0;
     End
    IF @acosValue<-1.0 
    Begin
    Set @acosValue=-1.0;
     End

    SET @Distance = acos(@acosValue)
     * @R;  

    RETURN @Distance  

END 
GO

Try this

試試這個

#4


0  

As the other answers have stated, you have a floating point issue, which will present itself differently based on different CPU architectures. However, there's a simple one-liner that fixes your issue:

正如其他答案所指出的那樣,您有一個浮點問題,它將以不同的CPU架構來呈現自己。但是,有一個簡單的一行代碼可以解決您的問題:

declare @dist float needs changed to declare @dist decimal(12, 10).

需要更改聲明@dist浮點數以聲明@dist decimal(12,10)。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2012/04/17/7298f488e247c06e1d55f94745e7152.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com