zoukankan      html  css  js  c++  java
  • ORACLE SQL 实现IRR的计算(二)

    上一版实现:https://www.cnblogs.com/Alex-Zeng/p/9334582.html

    上一版实现在某些情况下会计算出负值,与Excel的计算有差异。所以修改了实现方法。

    实现的具体代码如下:

    function IRR_ZEN(p_amount_array in typ_cashflow_array) RETURN NUMBER is
        rtn_err      number := 0;
        irrGuess     number := 0.01; -- default: 10%
        irr          number := 0.0;
        minDistance  number := 1E-15; --iteration: the smaller the distance, the smaller the interpolation
        maxIteration integer := 1000;
      
        wasHi         boolean := false;
        noOfCashFlows integer := 0;
        cashValue     number := 0.0;
        cashFlowStart number := 0.0;
      
        result_value number := 0.0;
      
      BEGIN
        irr           := irrGuess;
        result_value  := -999999;
        noOfCashFlows := p_amount_array.count;
      
        -- business startup costs
        cashFlowStart := p_amount_array(1); 
        
        for i in 1 .. maxIteration loop
          -- calculate cash value with current irr:
          cashValue := cashFlowStart; -- init with startup costs
        
          -- for each cash flow
          for j in 2 .. noOfCashFlows loop
            cashValue := cashValue + p_amount_array(j) / power(1.0 + irr, j-1);
          end loop;
        
          -- cash value is nearly zero
          if (abs(cashValue) < 0.0000000001) then
            -- dbms_output.put_line('abs(cashValue) < 0.0000000001 : '||to_char(cashValue));
            result_value := irr;
            exit;
          end if;
        
          -- adjust irr for next iteration:
          -- cash value > 0 => next irr > current irr
          if (cashValue > 0) then
            if wasHi then
              irrGuess := irrGuess / 2;
            end if;
          
            irr := irr + irrGuess;
          
            if wasHi then
              irrGuess := irrGuess - minDistance;
              wasHi    := false;
            end if;
          
          else
            -- cash value < 0 => next irr < current irr
            irrGuess := irrGuess / 2;
            irr      := irr - irrGuess;
            wasHi    := true;
          end if;
        
          -- estimated result too small to continue => end
          -- calculation
          if (irrGuess <= minDistance) then
            -- dbms_output.put_line('irrGuess <= minDistance : '||to_char(irrGuess));
            result_value := irr;
            exit;
          end if;
        end loop;
      
        return result_value;
      EXCEPTION
        WHEN OTHERS THEN
          dbms_output.put_line(substr(sqlerrm, 1, 640)); 
          return rtn_err;
      END IRR_ZEN;
  • 相关阅读:
    mvn 配置修改
    进制换算
    AT指令(中文详解版)二 [转载]
    Linux内核数据包处理流程-数据包接收(3)[转载]
    Linux内核数据包处理流程-数据包接收(2)[转载]
    Linux内核数据包处理流程-数据包接收(1)[转载]
    linux 内核模块 dumpstack
    linux c 用户态调试追踪函数调用堆栈以及定位段错误[转载]
    预处理命令详解(转载)
    [记录]博客开通
  • 原文地址:https://www.cnblogs.com/Alex-Zeng/p/12107703.html
Copyright © 2011-2022 走看看