XIRR 实现中的 bigdecimal/newton 错误

发布于 2024-11-27 08:14:57 字数 2510 浏览 1 评论 0 原文

我想使用 Ruby 中的 bigdecimal/newton 模块来实现 XIRR。我编写了一个脚本来尝试一下 这个例子

当我运行代码(Mac OS X 10.6 上的 Ruby 1.9.2)时,出现以下错误:

/opt/local/lib/ruby1.9/1.9.1/bigdecimal/ludcmp.rb:84:in `div': wrong number of arguments(2 for 1) (ArgumentError)
   from /opt/local/lib/ruby1.9/1.9.1/bigdecimal/ludcmp.rb:84:in `block in lusolve'
   from /opt/local/lib/ruby1.9/1.9.1/bigdecimal/ludcmp.rb:78:in `downto'
   from /opt/local/lib/ruby1.9/1.9.1/bigdecimal/ludcmp.rb:78:in `lusolve'
   from /opt/local/lib/ruby1.9/1.9.1/bigdecimal/newton.rb:60:in `nlsolve'
   from gistfile1.rb:52:in `<main>'

这是因为我的程序中出现错误,还是由于 BigDecimal 库?

#!/opt/local/bin/ruby1.9
require 'bigdecimal'
require 'bigdecimal/newton'
require 'time'
include Newton

transactions = [
  {amount:BigDecimal::new("-1000"), date:Time.parse("2011-01-01")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-02-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-03-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-04-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-05-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-06-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-07-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-08-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-09-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-10-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-11-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-12-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2012-01-11")},
]

class Function
  values ={ eps: "1.0e-16", one: "1.0", two: "2.0", ten: "10.0", zero: "0.0" }

  values.each do |key, value|
    define_method key do
      BigDecimal::new value
    end
  end

  def initialize(transactions)
    @transactions = transactions
  end

  def values(x)
    start = @transactions[0][:date]
    value = []

    value << @transactions.reduce(0) do |sum, t|
      pwr = (t[:date] - start) / 365
      r = t[:amount] / (1.0 + x[0]) ** pwr
      sum + r
    end

    value
  end
end

f = Function.new(transactions)
x = [f.zero]
n = nlsolve(f,x)
puts x

任何调试帮助将不胜感激。

谢谢!

I would like to use the bigdecimal/newton module in Ruby for an implementation of XIRR. I have written a script to try it out by following this example.

When I run the code (Ruby 1.9.2 on Mac OS X 10.6), I get the following error:

/opt/local/lib/ruby1.9/1.9.1/bigdecimal/ludcmp.rb:84:in `div': wrong number of arguments(2 for 1) (ArgumentError)
   from /opt/local/lib/ruby1.9/1.9.1/bigdecimal/ludcmp.rb:84:in `block in lusolve'
   from /opt/local/lib/ruby1.9/1.9.1/bigdecimal/ludcmp.rb:78:in `downto'
   from /opt/local/lib/ruby1.9/1.9.1/bigdecimal/ludcmp.rb:78:in `lusolve'
   from /opt/local/lib/ruby1.9/1.9.1/bigdecimal/newton.rb:60:in `nlsolve'
   from gistfile1.rb:52:in `<main>'

Is this because of an error in my program, or something in the
BigDecimal library?

#!/opt/local/bin/ruby1.9
require 'bigdecimal'
require 'bigdecimal/newton'
require 'time'
include Newton

transactions = [
  {amount:BigDecimal::new("-1000"), date:Time.parse("2011-01-01")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-02-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-03-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-04-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-05-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-06-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-07-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-08-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-09-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-10-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-11-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2011-12-11")},
  {amount:BigDecimal::new("100"), date:Time.parse("2012-01-11")},
]

class Function
  values ={ eps: "1.0e-16", one: "1.0", two: "2.0", ten: "10.0", zero: "0.0" }

  values.each do |key, value|
    define_method key do
      BigDecimal::new value
    end
  end

  def initialize(transactions)
    @transactions = transactions
  end

  def values(x)
    start = @transactions[0][:date]
    value = []

    value << @transactions.reduce(0) do |sum, t|
      pwr = (t[:date] - start) / 365
      r = t[:amount] / (1.0 + x[0]) ** pwr
      sum + r
    end

    value
  end
end

f = Function.new(transactions)
x = [f.zero]
n = nlsolve(f,x)
puts x

Any debugging assistance would be greatly appreciated.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

未蓝澄海的烟 2024-12-04 08:14:57

问题是您在计算中将 BigDecimals 与“正常”数字混合在一起。
尝试将 values 替换为:

values = { 
  eps: BigDecimal.new("1.0e-16"), 
  one: BigDecimal.new("1.0"), 
  two: BigDecimal.new("2.0"), 
  ten: BigDecimal.new("10.0"), 
  zero: BigDecimal.new("0.0") 
}

并将 def value(x) 中的块替换为

value << @transactions.reduce(0) do |sum, t|
  pwr = (t[:date] - start) / BigDecimal.new("365.0")
  r = t[:amount] / (BigDecimal.new("1.0") + x[0]) ** pwr
  sum + r
end

The problem is that you are mixing BigDecimals with "normal" numbers in your calculation.
Try to replace values by this:

values = { 
  eps: BigDecimal.new("1.0e-16"), 
  one: BigDecimal.new("1.0"), 
  two: BigDecimal.new("2.0"), 
  ten: BigDecimal.new("10.0"), 
  zero: BigDecimal.new("0.0") 
}

and the block in def values(x) by

value << @transactions.reduce(0) do |sum, t|
  pwr = (t[:date] - start) / BigDecimal.new("365.0")
  r = t[:amount] / (BigDecimal.new("1.0") + x[0]) ** pwr
  sum + r
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文