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;
  • 相关阅读:
    tomcat 服务器的几个重要监听 方法 与 使用
    webSocket 前端 js 加入 心跳机制 的基本写法
    Palinwords (处理回文串)
    Anti-Rhyme Pairs (求最长公共前缀)
    Extend to Palindrome (顺序Hash和逆序Hash处理回文)
    Milk Patterns (hash + 二分)
    次小生成树
    Borg Maze (BFS预处理+最小生成树)
    P1126 机器人搬重物
    P1141 01迷宫 (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/Alex-Zeng/p/12107703.html
Copyright © 2011-2022 走看看