我有以下代码试图解决多项式系统:
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)
。
为什么?
答案 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