0

背景を説明するために、私は現在、Access データベースとそのコードを SQL に移行するプロジェクトに取り組んでいます。

その過程で、Access のデータ型を SQL Server の に変更DoubleFloatました。これを行ったのは、これらのデータ型が密接に関連していることと、私のデータベースが多くの除算と乗算を実行しているためです (浮動小数点数が最適であると聞いたことがあります)。

データベースの変換に関するもう 1 つの問題は、Access がバンカーの丸めを使用するのに対し、SQL は使用しないという事実で発生しました。外に出て、2 つの UD バンカーの丸め関数を見つけました。両方とも、一貫したバンカーの丸め結果が得られません。

この不一致は、これらのバンカーの丸め関数 (減算と加算を含む) を浮動小数点数で実行しようとするときに予想されるものですか?

次の2つの機能があります...

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
4

1 に答える 1

1

SQL Server の ROUND() 関数は IEEE 標準 754 に準拠しており、float 型を使用する場合は「切り上げ」アルゴリズムを使用します。さらに精度が必要な場合は、10 進数を使用します。float または real を使用しないでください。

このリンクを参照してください http://msdn.microsoft.com/en-us/library/ms187912.aspx

于 2014-03-06T05:12:12.573 に答える