简体   繁体   English

R 中用于二分法的矢量化 IF

[英]vectorized IF for bisection method in R

ima beginner in R and i'm spending hours and hours trying to debug a function with IFELSE statement.我是 R 的初学者,我花了很多时间尝试使用 IFELSE 语句调试 function。 I know it could be kind of obvious but i can't find a solution.我知道这可能有点明显,但我找不到解决方案。 Here' s my problem.这是我的问题。

Using the same funcion with just an unknown factor everything works.使用具有未知因素的相同功能,一切正常。 here's my function:这是我的 function:

tir <- function(i){
 return((-45000 * 1-( 1 + i)^-3)/i + (1600000 * (1+i)^-3))
 }
tir(0.2)

> tir(0.2)
[1] 700923

Then i solve it with the bisection method to find the root.然后我用二分法求根来解决它。

bisec5 <- function(fun, a, b, tol=0.00001) {
  if (abs(fun(a)) < tol )
    return(a)
  if (abs(fun(b)) < tol )
    return(b)
  x <- (a + b) / 2
  if( abs(fun(x)) < tol )
    return(x)
  if (fun(a)*fun(x) < 0)
    return( Recall( fun, a, x, tol) )
  else
    return( Recall( fun, x, b, tol) )
}

bisec5(fun = tir, a= 50, b= 0.00000001)

[1] 4.380243

My issues begin when i'm tryng to solve the same equation for a vector.当我试图为一个向量求解相同的方程时,我的问题就开始了。 here the first function when the exponent of (1+i) is a number included between 2 and 28这里第一个 function 当 (1+i) 的指数是 2 到 28 之间的数字时

tir <- function(i){
    n<- 2:28
    return((-45000 * 1-( 1 + i)^-n)/i + (1600000 * (1+i)^-n))
}
tir(0.2)
[1]  886107.639  700923.032  546602.527  418002.106  310835.088  221529.240  147107.700   85089.750
 [9]   33408.125   -9659.896  -45549.913  -75458.261 -100381.884 -121151.570 -138459.642 -152883.035
[17] -164902.529 -174918.774 -183265.645 -190221.371 -196017.809 -200848.174 -204873.479 -208227.899
[25] -211023.249 -213352.707 -215293.923

Finally, how could i find the 28 roots of this equation applying the same method i used for 1?最后,我如何使用我用于 1 的相同方法找到该方程的 28 个根? Using the exactly the same function i just find the first root.使用完全相同的 function 我只是找到了第一个根。 therefore, I've tried using IFELSE, since the solution im looking for will be a vector, but i keep find errors.因此,我尝试使用 IFELSE,因为我正在寻找的解决方案将是一个向量,但我一直在寻找错误。 here's one example of my many tryings.这是我多次尝试的一个例子。

bisec5 <- function(fun, a, b, tol=0.00001) {
  ifelse (abs(fun(a)) < tol, a, "0" )
    
  ifelse (abs(fun(b)) < tol, print(b), next)
   
  x <- (a + b) / 2
  ifelse ( abs(fun(x)) < tol, print(x), next )
   
  ifelse (fun(a)*fun(x) < 0,return( Recall( fun, a, x, tol)), return( Recall( fun, x, b, tol)))
}
bisec5(fun = tir, a= 50, b =0.000001)
Error in ifelse(abs(fun(b)) < tol, print(b), next) : 
  no loop for break/next, jumping to top leve

Hope i coluld explain my problem as clear as possible, be comprehensive to any lack or mistake of terminology i made, and thanks in advance.希望我能尽可能清楚地解释我的问题,全面解决我所用术语的任何不足或错误,并在此先感谢。

I would offer a solution by using for loop (as suggested by @Érico Patto).我会通过使用for循环提供解决方案(正如@Érico Patto 所建议的那样)。

The idea is to create a vector with the length of n that contains your roots, and then apply tir function to each element of the vector.这个想法是创建一个包含根的长度为n的向量,然后将tir function 应用于向量的每个元素。 For example, n = 2:13 .例如, n = 2:13

First, create the vector, and assign NA as the initial values.首先,创建向量,并将NA指定为初始值。 Giving a name for each element would be a good idea.为每个元素命名将是一个好主意。

roots = rep(NA, length(n))
names(roots) = paste0("root for n = ", n)
roots
#root for n = 2  root for n = 3  root for n = 4  root for n = 5  root for n = 6  root for n = 7 
             NA              NA              NA              NA              NA              NA 
# root for n = 8  root for n = 9 root for n = 10 root for n = 11 root for n = 12 root for n = 13 
             NA              NA              NA              NA              NA              NA 

Then, set the exponent of (1+i) in tir function to n[k] .然后,将tir function 中(1+i)的指数设置为n[k] Here, k is a vector of the indices for n .此处, kn的索引向量。

tir_n <- function(i){
    return((-45000 * 1-( 1 + i)^-n[k])/i + (1600000 * (1+i)^-n[k]))
}

Then, by using for loop, apply the tir function to each element of n and assign the result to each element of roots .然后,通过使用for循环,将tir function 应用于n的每个元素,并将结果分配给roots的每个元素。

for (k in 1:length(n)) roots[k] <- bisec5(fun = tir, a= 50, b = 0.00000001)
roots
#root for n = 2  root for n = 3  root for n = 4  root for n = 5  root for n = 6  root for n = 7 
     33.5257269       4.3802426       1.8465317       1.0706831       0.7145925       0.5148502 
# root for n = 8  root for n = 9 root for n = 10 root for n = 11 root for n = 12 root for n = 13 
      0.3884500       0.3016256       0.2381644       0.1892135       0.1491551       0.1126293 

The result shows that for n = 3 , the root is 4.3802426 , which matches your result.结果显示对于n = 3 ,根是4.3802426 ,这与您的结果相匹配。

I set n=2:13 instead of n=2:28 because in my computer, the latter generates an error because its usage of C stack is too close to the limit of the C stack size in my computer, and I don't want to change the limit.我设置n=2:13而不是n=2:28因为在我的计算机中,后者会产生错误,因为它对 C 堆栈的使用太接近我计算机中 C 堆栈大小的限制,我不这样做想改变限制。 In case you encounter this kind of error and you want to change your C stack size limit, you can refer to this thread Error: C stack usage is too close to the limit如果您遇到这种错误并且想要更改您的 C 堆栈大小限制,您可以参考此线程错误:C 堆栈使用量太接近限制

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM