2012-11-01 54 views
1

在數學上,這些結果是相似的,我只是好奇他們的行爲。第一個版本,當我的本地變量被聲明爲一個浮點數時,舍入函數停止顯示小數點後第二位的小數位數。在局部變量聲明爲int的第二個版本中,round函數四捨五入至小數點後兩位,然後添加一堆零。爲什麼變量類型會導致round函數的行爲不同?Casting as float vs int returns不同的結果

declare @totalpop float 
set @totalpop = (select count(distinct patid) from members) 
select @totalpop 
select edutext 
,COUNT(*) as educationCounts 
,round(100.0*COUNT(*)/@totalpop,2) 
from 
(
select distinct m.patid, e.eduText 
    from members as m 
    inner join EducationTable as e on e.eduID = m.education 
)x 
group by x.eduText 

--doesn't圓到小數點後兩位

declare @totalpop int 
set @totalpop = (select count(distinct patid) from members) 
select @totalpop 
select edutext 
,COUNT(*) as educationCounts 
,round(100.0*COUNT(*)/@totalpop,2) 
from 
(
select distinct m.patid, e.eduText 
    from members as m 
    inner join EducationTable as e on e.eduID = m.education 
)x 
group by x.eduText 
+4

[每個計算機科學家應該知道的關於浮點算術](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Jamiec

+0

+1 to @Jamiec for the epic reference ,甚至脫離主題! ;-) –

回答

1

首先,讓我們來看看ROUND()函數的定義:

Returns a numeric value, rounded to the specified length or precision. 

它說ROUNDED到指定的長度,而不是TRUNCATED到指定的長度。

現在,使用int和float會生成完全不同的表達式類型。你可以用下面的查詢很容易對它們進行比較(我切換COUNT(*)爲1,@totalpop 1也):

Select sql_variant_property(100.0 * 1/convert(int, 1), 'BaseType') BaseType, 
     sql_variant_property(100.0 * 1/convert(int, 1), 'Precision') Precision, 
     sql_variant_property(100.0 * 1/convert(int, 1), 'Scale') Scale 

Select sql_variant_property(100.0 * 1/convert(float, 1.0), 'BaseType') BaseType, 
     sql_variant_property(100.0 * 1/convert(float, 1.0), 'Precision') Precision, 
     sql_variant_property(100.0 * 1/convert(float, 1.0), 'Scale') Scale 

這就告訴我們,使用一個int,表達給你一個數字。使用浮動,你會得到一個浮動。根據微軟的說法,他們的ROUND函數在傳遞一個float時會返回一個float,在傳遞一個numeric時會返回一個小數。

您可以在那裏閱讀所有關於它:在最後http://msdn.microsoft.com/en-us/library/ms175003.aspx

,你可以看到,零開始時的浮動獲取的截斷,數字永遠不會被截斷,直到它達到規模上限:

select CONVERT(float, 3.330000),   -- 3.33 
     CONVERT(numeric(17, 12), 3.330000) -- 3.330000000000