2014-03-04 2 views
1

이것은 경험이있는 사람들에게 간단해야합니다. R을 사용하여 방정식을 풀고 싶습니다. Solve()를 사용하여 다른 선형/이차 방정식을 풀 수 있음을 알고 있습니다.이런 식의 상징적 인 함수를 풀 때 R

하지만 이런 일이 :

1/20 = 1/8 * (1/(12+x)) + 1/4*(1/(40+x)) + 3/4*(1/(50+x)) 

가 어떻게이 경우 X를 해결할 수 있습니까? 그것은 손으로 할 수 없습니다. TI83에서와 같이 문제를 해결하는 데 필요한 숫자 방법이 필요합니다.

코드 줄을 작성하지 않고 R에서이 작업을 수행하는 간단하고 빠른 방법이 있습니까? 감사합니다.

+0

[Ryacas package] (http://cran.r-project.org/web/packages/Ryacas/)를 보시면 도움이 될 것입니다. – Barranka

답변

4

당신이 말한 것처럼 실제로 뿌리가 있습니다.

f <- function(x) {1/20 - 1/8 * (1/(12+x)) + 1/4*(1/(40+x)) + 3/4*(1/(50+x))} 
x <- seq(-100,100) 
par(mar=c(2,2,1,2))  # this just minimizes plot margins 
plot(x,f(x), type="l") 
abline(0,0,col="blue",lty=2) 
그래서 분명히 f(x)가하는 크로스 0 여러 번 : 우선 함수를 플롯하는 것입니다.

다음 단계는 교차점을 추정하는 것입니다. 이렇게하는 한 가지 방법은 기호의 변화를 볼 수 있습니다 :

x <- seq(-75,0,0.001) 
y <- sign(f(x))      # vector of +1 or -1 
plus.to.minus <- which(diff(y)<0) # diff(y)<0 when f crosses from (+) to (-) 
minus.to.plus <- which(diff(y)>0) # diff(y)>0 when f crosses from (-) to (+) 
# first two roots are (+) to (-); third is (-) to (+) 
lower <- c(plus.to.minus[1:2],minus.to.plus[3]) 
roots <- sapply(lower,function(i)uniroot(f,interval=c(x[i],x[i+1]))$root) 
lapply(roots,function(x) points(roots,c(0,0,0),col="red",pch=16)) 
roots 
# [1] -67.38961 -41.72593 -10.38446 

이 코드는 xf(x) 변경 서명 찾으려고 시도합니다. 실제로 f(x)이 부호를 변경할 수있는 두 가지 이유가 있습니다 : 루트 또는 점근선. 당신의 경우에는 3 개의 뿌리와 3 개의 점근선이 있습니다. 여기서 성공은 x가 충분히 작아 교차로를 완전히 놓치지 않는 것에 달려 있습니다. 위의 그래프를 보면 0.001 정도면 충분합니다. 여기

, y는 (+1 또는 -1 등의) 기호 (F)의 벡터를 포함 -75 0 x 사이에서 0.001 단위이다. 한계 (-75,0)는 위 도표를 검사하여 선택되었습니다. 우리는 세 가지 뿌리가 있다는 것을 시각적으로 볼 수 있습니다. 첫 번째 두 개는 (+)에서 (-)까지 교차하고 세 번째는 (-)에서 (+)까지 교차합니다. 따라서 교차가 발생하는 x의 인덱스 ( which(...) 사용)를 확인한 다음 처음 두 요소 인 plus.to.minus과 세 번째 요소 인 minus.to.plus을 포함하는 벡터를 만듭니다. 그런 다음 increment=c(x[i],x[i+1])을 사용하여 uniroot(...)으로 전화합니다. 여기서 i은 적절한 교차점의 색인입니다.

마지막으로 우리는 실제로 우리가 뿌리를 찾았 음을 확인하기 위해 결과를 플로팅합니다.이것은 정말로 중요합니다. 항상 항상 결과를 그립니다. uniroot(...)은 점근선이있는 곳에 "루트"를 찾을 것이므로 실제 루트를 찾았는지 확인해야합니다.

+0

고마워요! 우리는 뿌리 주변의 답을 찾고 있음을 나타 내기 위해 끝에 $ root를 추가해야합니까? – lulumink

+0

'uniroot (...)'문서를보십시오. 여러 요소가있는 목록을 반환합니다. 'uniroot $ root'는 루트의 값입니다. 'uniroot $ f.root'는 루트에있는 함수의 값입니다 (0에 가깝지만 0은 아님). – jlhoward

+0

감사합니다! 나는 확실히 그것을 들여다 볼 것이다. – lulumink

2

사용 uniroot() 하나 개의 변수 방정식을 해결하기 위해 : 함수, f에, 나는 1/20을 빼는 것을

f <- function(x){ 
    1/8 * (1/(12+x)) + 1/4*(1/(40+x)) + 3/4*(1/(50+x)) - 1/20 
} 
uniroot(f, interval = c(-1e+08, 1e+08)) 

알 수 있습니다. 이는 uniroot()이 함수의 0을 찾기 때문입니다. 이 경우

, 당신은 오류 얻을 것이다 :

Error in uniroot(f, interval = c(-1e+08, 1e+08)) : 
    f() values at end points not of opposite sign 

는이 문제를 해결하기를, 당신은 제로가 존재 확인해야하고 않는 경우, 그 F 있도록 간격을, (A, B) 이동 (a) == -f (b)

+0

입력 해 주셔서 감사합니다. 출력에 오류가있는 이유는 무엇입니까? 나는 똑같은 것을 시도해 보았다. 함수에 대해 0으로 설정했다고해도 여기에 무슨 문제가 있습니까? – lulumink

+0

그 간격에서 0에 대한 해가 없기 때문입니다. 0이 존재하는지 확인해야하고, 그렇다면'f (a) == -f (b)'가되도록'(a, b)'간격을 이동해야합니다. –

+0

나는 내가 가지고있는 다른 기능에 대한 해결책이 있다는 것을 확신한다. 그것은 여전히 ​​나에게이 오류를 준다. – lulumink

관련 문제