2014-03-05 78 views
0

爲了提供一些背景知識,我目前正在開發一個將Access數據庫及其代碼轉換爲SQL的項目。Float數據類型將不會與銀行家四捨五入 - SQL Server 2008

在此過程中,我在SQL Server中將Access數據類型Double更改爲Float;我這樣做是因爲這些數據類型是密切相關的,因爲我的數據庫執行了很多分割和乘法(我聽說漂浮最適合)。

轉換數據庫的另一個問題出現在Access使用銀行家四捨五入的事實,而SQL沒有;我走出去,發現兩個UD銀行家四捨五入的功能,都沒有讓一致的銀行家圓滿結果,因爲他們應該。

這是不一致的東西,當我試圖運行這些銀行家四捨五入的功能(其中包括減法和加法)浮點數時,我應該期望嗎?

以下是這兩個功能......

FUNCTION [dbo].[RB](@Val FLOAT, @Digits INT) 
RETURNS FLOAT 
AS 
BEGIN 
RETURN CASE WHEN ABS(@Val - ROUND(@Val, @Digits, 1)) * POWER(10, @Digits+1) = 5 
      THEN ROUND(@Val, @Digits, CASE WHEN CONVERT(INT, ROUND(ABS(@Val) * 
         POWER(10,@Digits), 0, 1)) % 2 = 1 THEN 0 ELSE 1 END) 
      ELSE ROUND(@Val, @Digits) 
     END 
END 


FUNCTION [dbo].[RoundBanker] 
(@Amt NUMERIC(38,16) 
, @RoundToDecimal TINYINT 
) 
RETURNS NUMERIC(38,16) 
AS 
BEGIN 
DECLARE @RoundedAmt NUMERIC(38,16) 
, @WholeAmt  INT 
, @Decimal  TINYINT 
, @Ten   NUMERIC(38,16) 
SET @Ten  = 10.0 
SET @WholeAmt = ROUND(@Amt,0, 1) 
SET @RoundedAmt = @Amt - @WholeAmt 
SET @Decimal = 16 
WHILE @Decimal > @RoundToDecimal 
BEGIN 
SET @Decimal = @Decimal - 1 
IF 5 = (ROUND(@RoundedAmt * POWER(@Ten, @Decimal + 1) ,0,1) - 
     (ROUND(@RoundedAmt * POWER(@Ten, @Decimal) ,0,1) * 10)) 
AND 0 = cast((ROUND(@RoundedAmt * POWER(@Ten, @Decimal) ,0,1) - 
    (ROUND(@RoundedAmt * POWER(@Ten, @Decimal - 1) ,0,1) * 10)) 
    AS INTEGER) % 2 
    SET @RoundedAmt = ROUND(@RoundedAmt,@Decimal, 1) 
ELSE 
    SET @RoundedAmt = ROUND(@RoundedAmt,@Decimal, 0) 
END 
RETURN (@RoundedAmt + @WholeAmt) 
END 
+3

如果要存儲的號碼,財務計算,你應該使用'decimal',定點格式。如果你將數字轉換爲字符串,我會建議'str()'函數。 –

+2

考慮使用Money/Smallmoney,它也有更好的性能。銀行家四捨五入是財務。順便說一下,強制它是微不足道的。 – TomTom

+0

@TomTom我覺得這很平凡 – codingManiac

回答

1

SQL服務器ROUND()函數遵循IEEE標準754,並使用「四捨五入」的算法,當你使用float類型。如果您需要更高精度,請使用小數點不要使用float或real。

參考此鏈接http://msdn.microsoft.com/en-us/library/ms187912.aspx

+0

我最終將我的浮動數據轉換爲十進制數,將它傳遞給UDF銀行家四捨五入函數,然後將其存回爲浮動,並且它工作得很好 – codingManiac