Ruby Newton方法给出了错误的结果?

时间:2014-11-14 12:32:15

标签: ruby math

我有以下代码试图解决多项式系统:

require "bigdecimal"
require "bigdecimal/newton"
include Newton

class Function
  attr_reader :zero, :one, :two, :ten, :eps
  def initialize()
    @zero = BigDecimal::new("0.0")
    @one  = BigDecimal::new("1.0")
    @two  = BigDecimal::new("2.0")
    @ten  = BigDecimal::new("10.0")
    @eps  = BigDecimal::new("1.0e-16")
  end

  def values(x) # <= defines functions solved
    f = []
    f1 = x[0] + x[1] - 7
    f2 = x[0]*x[0] + x[1]*x[1] - 29
    f <<= f1
    f <<= f2
    f
  end
end
f = Function.new
x = [f.zero,f.zero]
nlsolve(f,x)
puts x.map(&:to_i)

输出[1,5]。显然应该是[2,5],因为这是系统的正确解决方案:

x + y = 7
x*x + y*y = 29

也许罪魁祸首是我to_i BigDecimal号召唤,但这不应该像数学一样。

有什么想法吗?

奖金问题

ruby​​ stdlib说你可以在没有BigDecimal的情况下使用它,但是将浮点数传递给initialize中的所有变量都会给我这个错误:

ruby/2.1.0/bigdecimal/ludcmp.rb:23:in 'div': wrong number of arguments (2 for 1) (ArgumentError)

为什么?

2 个答案:

答案 0 :(得分:2)

关于红利问题:

我认为问题在于bigdecimal / ludcmp.rb:

https://github.com/lian/ruby-bigdecimal-backport/blob/master/lib/bigdecimal/ludcmp.rb

在第23行,它在'one'上调用div方法

scales <<= one.div(nrmrow,prec)
你以float形式传入的

,但是float的div方法接受一个参数,而bigdecimal则需要两个。如果您将初始化中的所有变量更改为浮点数但保留

@one  = BigDecimal::new("1.0")

它将使它超过ludcmp.rb的第23行(尽管在代码中稍后仍出现同样的错误)。

答案 1 :(得分:1)

您应该使用x.map(&:round)

在ruby中的浮点数上调用.to_i时,你的精度会降低。

示例 -

1.999999999.to_i == 1 #=> true

在这种情况下,您可以调用.round来获得预期的输出。即 -

1.999999999.round == 2 #=> true