为了提供一些背景知识,我目前正在开展一个将 Access 数据库及其代码转换为 SQL 的项目。
在此过程中,我在 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