求解代数方程
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 使用 Ryacas
包 solve
如下所示。 (感谢@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变量,这里h
在eq2
中被引用,那么用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 或使用上面的 eq
和 Ryacas0
包:
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 我们有 B
和 A
是实部和虚部那种表情。没有使用包。
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
我正在尝试求解这个等式:((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 使用 Ryacas
包 solve
如下所示。 (感谢@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变量,这里h
在eq2
中被引用,那么用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 或使用上面的 eq
和 Ryacas0
包:
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 我们有 B
和 A
是实部和虚部那种表情。没有使用包。
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