-1

我有一个同事写了一个 IRR 计算函数。您提供似乎是一组现金流量,它会返回 IRR。它在 99% 的时间内都有效,但有时我会遇到浮点错误。我试图找出代码中可能发生的位置。该函数如下所示:

CREATE FUNCTION [dbo].[CalcXIRR]
(
    @Sample XIRRTable READONLY,
    @Rate FLOAT = 0.1
)
RETURNS DECIMAL(38, 9)
AS
BEGIN

    DECLARE @X FLOAT = 0.0,
    @X0 FLOAT = 0.1,
    @f FLOAT = 0.0,
    @fbar FLOAT = 0.0,
    @i TINYINT = 0,
    @found TINYINT = 0

    IF @Rate IS NULL
        SET @Rate = 0.1

    SET @X0 = @Rate

    WHILE @i < 100
    BEGIN

        SELECT  @f = 0.0, 
                @fbar = 0.0

        SELECT  @f = @f + value * POWER(1 + @X0, (-theDelta / 365.0E)),
                @fbar = @fbar - theDelta / 365.0E * value * POWER(1 + @X0, (-theDelta / 365.0E - 1))
        
        FROM    
        (
            SELECT  Value,
                    DATEDIFF(DAY, MIN(date) OVER (), date) AS theDelta

            FROM    @Sample

        ) AS d

        SET @X = @X0 - @f / @fbar

        IF ABS(@X - @X0) < 0.00000001
        BEGIN
            SET @found = 1
            BREAK;
        END

        SET @X0 = @X
        SET @i += 1

    END

    IF @found = 1
        RETURN  @X

    RETURN NULL
END
GO

您为其提供如下所示的数据:

Date                     Value
2017-08-01 00:00:00.000 -3775585
2017-08-01 00:00:00.000 -10763.73
2017-08-01 00:00:00.000 -10763.73
2017-08-01 00:00:00.000 10763.73
2017-08-01 00:00:00.000 10763.73
2017-08-01 00:00:00.000 3775585
2017-08-01 00:00:00.000 3786348.73
2017-08-02 00:00:00.000 -1550780
2017-08-02 00:00:00.000 -4823
2017-08-02 00:00:00.000 -4823
2017-09-11 00:00:00.000 -254800
2017-09-11 00:00:00.000 254800
4

1 回答 1

0

有没有理由不使用小数而不是浮点数?

请参阅Bert Wagner 的此链接

这是它的摘录:

浮点数学错误可以通过几种方式修复。

一种选择是停止关心他们。浮点数上发生的错误非常小(尽管当通过算术复合时,错误可能会变得足够大以至于像我的报告条形图示例中那样引人注目)。如果您正在编写查询或报告,其中很少有错误无关紧要,那么您可以继续您的快乐方式而无需更改任何内容。

第二个选择是仍然将值存储为浮点数(为了节省存储空间),但要确保您的应用程序代码具有正确舍入精确数字的业务逻辑。

但是,如果您的数据需要每次都完全准确且没有错误,请使用不同的数据类型。这里的逻辑选择是在 SQL Server 中使用十进制,它使用不同的内部方法来存储您的数字,每次都能产生完美的结果。但是,可能值的范围没有浮点数那么大,您将为该精度付出额外字节的存储空间。

最后,浮点对于许多应用程序来说已经足够好了。重要的是您意识到这些错误可能会发生并且您会适当地处理它们。

于 2020-06-26T18:49:36.303 回答