求解代数方程

Solving an algebraic equation

我正在尝试求解这个等式:((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) =1

有没有办法用 R 做到这一点?

尝试使用不正确的解决方案:

library(Ryacas)
eq <- "((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 "
# simplify the equation:
library(glue)
yac_str(glue("Simplify({eq})"))
library(evaluate)
evaluate(eq,list(x=c(0,1,10,100,-100)))

evaluate() 只是 returns 等式:

"((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 " 

等式的答案是 −2004200

听起来您想 Solve() 得到 x,而不仅仅是简化...?以下代码求解方程,从解中去除 x==,并对表达式求值:

eq2 <- gsub("x==","",yac_str(glue("Solve({eq},x)")))
[1] "{(-0.80168e6)/0.4}"
eval(parse(text=eq2))
[1] -2004200

这是一个基本的 R 解决方案。
将等式改写成函数形式,用curve得到函数符号不同的两个端点,将uniroot代入

f <- function(x) ((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) - 1
curve(f, -1e7, 1)
uniroot(f, c(-1e7, 1))
#$root
#[1] -2004200
#
#$f.root
#[1] 0
#
#$iter
#[1] 1
#
#$init.it
#[1] NA
#
#$estim.prec
#[1] 7995800

根据问题评论中的讨论,这里有一个通用的解决方案。要找到其根的函数现在接受参数 params 以传递租金、薪水、工人数量、价格、单位成本和资本成本的值。此参数必须是命名列表。

f <- function(x, K = 1, params) {
  A <- with(params, rent + salary*workers)
  with(params, (A + (x + A)*capitalcost)/(price - unitcost) - K)
}

params <- list(
  rent = 2300, 
  salary = 1900, 
  workers = 1, 
  price = 600, 
  unitcost = 400, 
  capitalcost = 0.002
)
curve(f(x, params = params), -1e7, 1)
uniroot(f, c(-1e7, 1), params = params)

如果你想要快速的东西:rootSolve图书馆是你的首选。

library(rootSolve)
func_ <- function(x) ((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400)-1
uniroot.all(func_, c(-1e9, 1e9))
[1] -2004200

请注意,大多数时候减少间隔会更好。

如果您要保持相同的结构,那么在 Base R 中,您可以这样做:

solveX <- function(eq){
  U <- function(x)abs(eval(parse(text = sub("=+","-", eq)), list(x=x)))
  optim(0, U, method = "L-BFGS-B")$par
}
eq <- "((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 "
solveX(eq)
[1] -2004200

1) Ryacas 使用 Ryacassolve 如下所示。 (感谢@mikldk 对最后一行的改进。)

library(Ryacas)
eq <- "((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 "  # from question

res <- solve(ysym(eq), "x")
as_r(y_rmvars(res))  # extract and convert to R
## [1] -2004200

如果eq里面有R变量,这里heq2中被引用,那么用eval计算结果。

h <- 2300
eq2 <- "((h+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 "  # from question
res2 <- solve(ysym(eq2), "x")
eval(as_r(y_rmvars(res2)))
## [1] -2004200

2) Ryacas0 或使用上面的 eqRyacas0 包:

library(Ryacas0)

res <- Solve(eq, "x")
eval(Expr(res)[[1:3]]) # convert to R
## [1] -2004200

3a) 基数 R 鉴于这是一个线性方程和下面的解,其中 A 是斜率,B 是截距:

A * x + B = 0

x = - B / A

如果我们用虚部 1i 替换 x 然后将 rhs 移动到 lhs 我们有 BA 是实部和虚部那种表情。没有使用包。

r <- eval(parse(text = sub("==", "-", eq)), list(x = 1i))
-Re(r) / Im(r)
## [1] -2004200

3b) 如果我们将 rhs 移动到 lhs,那么 B 在 x=0 处等于它,A 等于 x 的导数,所以另一个基 R 解是:

e <- parse(text = sub("==", "-", eq))
- eval(e, list(x = 0)) / eval(D(e, "x"))
## [1] -200420