Тип данных с плавающей точкой не будет работать с округлением банкиров - SQL Server 2008
Чтобы дать некоторое представление, я сейчас работаю над проектом по переводу базы данных Access и ее кода на SQL.
В процессе я изменил типы данных Access Double
в Float
в SQL Server; Я сделал это, потому что эти типы данных тесно связаны, и потому что моя база данных выполняет много делений и умножений (что, как я слышал, было лучше для поплавков).
Другая проблема преобразования базы данных возникла в связи с тем, что 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
1 ответ
Функция SQL Server ROUND() соответствует стандарту IEEE 754 и использует алгоритм округления при использовании типа с плавающей запятой. Используйте десятичную дробь, если вам нужно больше точности. не используйте использовать float или real.
обратитесь по этой ссылке http://msdn.microsoft.com/en-us/library/ms187912.aspx