이 페이지의 최신 내용은 아직 번역되지 않았습니다. 최신 내용은 영문으로 볼 수 있습니다.

수치적으로 방정식 풀기

Symbolic Math Toolbox™는 수치 방정식 솔버 및 기호 방정식 솔버를 다 제공합니다. 수치 솔버와 기호 솔버의 비교는 Select Numeric or Symbolic Solver 항목을 참조하십시오. 방정식 또는 연립방정식에는 해가 여러 개 있을 수 있습니다. 이들 해를 수치적으로 구하려면 함수 vpasolve를 사용하십시오. 다항 방정식의 경우 vpasolve는 모든 해를 반환합니다. 비다항 방정식의 경우 vpasolve는 구한 해 중 첫 번째 해를 반환합니다. 여기서는 vpasolve를 사용하여 다항 방정식과 비다항 방정식의 해를 구하고 이들 해를 임의의 정밀도까지 얻는 방법을 보여줍니다.

다항식 함수의 모든 근 구하기

vpasolve를 사용하여 함수 f(x)=6x72x6+3x38의 모든 해를 구합니다.

syms f(x)
f(x) = 6*x^7-2*x^6+3*x^3-8;
sol = vpasolve(f)
sol =
                                          1.0240240759053702941448316563337
 - 0.88080620051762149639205672298326 + 0.50434058840127584376331806592405i
 - 0.88080620051762149639205672298326 - 0.50434058840127584376331806592405i
 - 0.22974795226118163963098570610724 + 0.96774615576744031073999010695171i
 - 0.22974795226118163963098570610724 - 0.96774615576744031073999010695171i
    0.7652087814927846556172932675903 + 0.83187331431049713218367239317121i
    0.7652087814927846556172932675903 - 0.83187331431049713218367239317121i 

이 함수는 7차 다항식이므로 vpasolve는 예상대로 이 함수의 근 7개를 반환합니다.

검색 범위와 시작점을 사용하여 비다항식 함수의 영점 찾기

함수 f(x)=e(x/7)cos(2x)를 예로 들어 보겠습니다. 이 함수의 플롯을 보면 x가 증가함에 따라 영점에서의 기울기가 증가하는 주기적인 영점들이 있습니다.

syms x
h = fplot(exp(x/7)*cos(2*x),[-2 25]);
grid on

vpasolve를 사용하여 함수 f의 영점 하나를 찾습니다. vpasolve는 복수의 해가 존재하는 경우에도 비다항 방정식의 해 하나만 반환합니다. 반복해서 호출하더라도 vpasolve는 동일한 결과를 반환하는데, 이는 복수의 영점이 존재하는 경우에도 그렇습니다.

f = exp(-x/20)*cos(2*x);
for i = 1:3
	vpasolve(f,x)
end
ans =
19.634954084936207740391521145497
ans =
19.634954084936207740391521145497
ans =
19.634954084936207740391521145497

복수의 해를 구하려면 옵션 randomtrue로 설정하십시오. 이렇게 하면 vpasolve가 시작점을 임의로 선택합니다. 임의의 시작점을 선택하는 알고리즘에 대한 자세한 내용은 vpasolve 페이지의 알고리즘 항목을 참조하십시오.

for i = 1:3
		vpasolve(f,x,'random',true)
end
ans =
-226.98006922186256147892598444194
ans =
98.174770424681038701957605727484
ans =
58.904862254808623221174563436491

x = 10에 가까운 영점과 x = 1000에 가까운 영점을 찾으려면 시작점을 10으로 설정한 다음, 1000으로 설정하십시오.

vpasolve(f,x,10)
vpasolve(f,x,1000)
ans =
10.210176124166828025003590995658
ans =
999.8118620049516981407362567287

15x25 범위 내에 있는 영점을 찾으려면 검색 범위를 [15 25]로 설정하십시오.

vpasolve(f,x,[15 25])
ans =
21.205750411731104359622842837137

[15 25] 범위 내에 있는 복수의 영점을 찾으려는 경우, 이전에 보여진 것처럼 호출할 때마다 동일한 결과가 반환되므로 vpasolve를 반복해서 호출할 수 없습니다. 대신, 검색 범위와 함께 randomtrue로 설정하십시오.

for i = 1:3
vpasolve(f,x,[15 25],'random',true)
end
ans =
21.205750411731104359622842837137
ans =
16.493361431346414501928877762217
ans =
16.493361431346414501928877762217

random 옵션을 지정하고 동시에 시작점을 지정할 경우 vpasolve는 두 옵션은 호환되지 않는다는 경고를 표시합니다.

vpasolve(f,x,15,'random',true)
Warning: 'Random' has no effect because
 all variables have a starting value. 
> In sym/vpasolve (line 168) 
ans =
14.922565104551517882697556070578

아래의 함수 findzeros를 생성하여 허용오차 범위에서 주어진 검색 범위 내에 있는 f의 모든 영점을 체계적으로 찾아 보겠습니다. 이 절차는 우선 입력 검색 범위를 지정하고 vpasolve를 호출하여 영점 하나를 찾습니다. 그런 다음 이 영점의 값을 기준으로 검색 범위를 둘로 분할한 후 새로운 검색 범위를 입력값으로 사용하여 자기 자신을 재귀적으로 호출함으로써 더 많은 영점을 찾습니다. 첫 번째 입력값은 함수이고, 두 번째 입력값은 범위이며, 선택적으로 세 번째 입력값에는 영점과 영점으로부터 생성된 상한 및 하한 사이의 오차를 지정할 수 있습니다.

이 함수는 여기에서 섹션별로 설명합니다.

입력값 2개와 출력값 1개를 갖는 함수를 선언합니다.

function sol = findzeros(f,range,err)

선택적인 허용오차 인수를 지정하지 않으면 findzeroserr0.001로 설정합니다.

if nargin < 2
    err = 1e-3;
end

vpasolve를 사용하여 검색 범위 내에서 영점 하나를 찾습니다.

sol = vpasolve(f,range);

vpasolve가 영점을 찾지 못하면 종료합니다.

if(isempty(sol))
    return

vpasolve는 영점을 찾으면 검색 범위를 이 영점 위에 그리고 아래에 하나씩, 2개의 검색 범위로 분할합니다.

else
    lowLimit = sol-err;
    highLimit = sol+err;

아래의 검색 범위를 사용하여 findzeros를 호출합니다. findzeros가 영점을 반환할 경우, 값을 해 배열에 복사하고 정렬합니다.

    temp = findzeros(f,[range(1) lowLimit],1);
    if ~isempty(temp)
        sol = sort([sol temp]);
    end

위의 검색 범위를 사용하여 findzeros를 호출합니다. findzeros가 영점을 반환할 경우, 값을 해 배열에 복사하고 정렬합니다.

    temp = findzeros(f,[highLimit range(2)],1);
    if ~isempty(temp)
        sol = sort([sol temp]);
    end
    return
end
end

전체 함수 findzeros는 다음과 같습니다.

function sol = findzeros(f,range,err)
if nargin < 3
    err = 1e-3;
end
sol = vpasolve(f,range);
if(isempty(sol))
    return
else
    lowLimit = sol-err;
    highLimit = sol+err;
    temp = findzeros(f,[range(1) lowLimit],1);
    if ~isempty(temp)
        sol = sort([sol temp]);
    end
    temp = findzeros(f,[highLimit range(2)],1);
    if ~isempty(temp)
        sol = sort([sol temp]);
    end
    return
end
end

findzeros를 검색 범위 [10 20]을 사용해 호출하여 디폴트 허용오차 내에서 이 범위 내에 있는 f(x) = exp(-x/20)*cos(2*x)의 모든 영점을 찾습니다.

syms f(x)
f(x) = exp(-x/20)*cos(2*x);
findzeros(f,[10 20])
ans =
[ 10.210176124166828025003590995658, 11.780972450961724644234912687298,...
 13.351768777756621263466234378938, 14.922565104551517882697556070578,...
 16.493361431346414501928877762217, 18.064157758141311121160199453857,...
 19.634954084936207740391521145497]

임의의 정밀도까지의 해 얻기

digits를 사용하여 해의 정밀도를 설정합니다. 기본적으로 vpasolve는 유효 숫자 32개 정밀도까지의 해를 반환합니다. digits를 사용하여 정밀도를 유효 숫자 64개로 늘립니다. digits를 수정할 때는 현재 값을 복원할 수 있도록 먼저 저장해 두어야 합니다.

f = exp(x/7)*cos(2*x);
vpasolve(f)
digitsOld = digits;
digits(64)
vpasolve(f)
digits(digitsOld)
ans =
-7.0685834705770347865409476123789
ans =
-7.068583470577034786540947612378881489443631148593988097193625333

검색 범위를 사용하여 다변량 방정식 풀기

다음과 같은 연립방정식이 있다고 가정해 보겠습니다.

z=10(cos(x)+cos(y))z=x+y20.1x2yx+y2.7=0

0 ≤ x ≤ 2.50 ≤ x ≤ 2.5에 대해 방정식을 플로팅하면 3개의 곡면이 2개의 점에서 교차하는 것을 볼 수 있습니다. 플롯을 더 잘 시각화하려면 view를 사용하십시오. 컬러맵 값을 스케일링하려면 caxis를 사용하십시오.

syms x y z
eqn1 = z == 10*(cos(x) + cos(y));
eqn2 = z == x+y^2-0.1*x^2*y;
eqn3 = x+y-2.7 == 0;
equations = [eqn1 eqn2 eqn3];
fimplicit3(equations)
axis([0 2.5 0 2.5 -20 10])
title('System of Multivariate Equations')
view(69, 28)
caxis([-15 10])

vpasolve를 사용하여 곡면이 교차하는 점을 찾습니다. 함수 vpasolve는 구조체를 반환합니다. 해에 액세스하려면 구조체의 요소를 참조하십시오.

sol = vpasolve(equations);
[sol.x sol.y sol.z]
ans = (2.36974772245479792091013371601740.330252277545202079089866283982612.2933543768232277431243854708612)

해 공간의 특정 영역을 검색하려면 변수에 대해 검색 범위를 지정하십시오. 범위 0x1.51.5y2.5를 지정하면 vpasolve 함수는 아래 그림에 표시된 경계 내 영역을 검색합니다.

vpasolve를 사용하여 이 검색 범위 0x1.51.5y2.5에 대한 해를 구합니다. z의 검색 범위를 생략하려면 검색 범위를 [NaN NaN]으로 설정하십시오.

vars = [x y z];
range = [0 1.5; 1.5 2.5; NaN NaN];
sol = vpasolve(equations, vars, range);
[sol.x sol.y sol.z]
ans = (0.910626617256333611769500315510691.78937338274366638823049968448933.9641015721356254724107884666807)

복수의 해를 구하려면 random 옵션을 true로 설정하면 됩니다. 이렇게 하면 vpasolve가 실행할 때마다 임의의 시작점을 사용합니다. vpasolve가 특정 검색 범위 내에서 임의의 시작점을 사용하도록 random 옵션을 검색 범위와 함께 사용할 수 있습니다. random은 시작점을 임의로 선택하므로, 연속된 호출에서 동일한 해가 구해질 수도 있습니다. 두 해를 모두 찾으려면 vpasolve를 반복적으로 호출하십시오.

clear sol
range = [0 3; 0 3; NaN NaN];
for i = 1:5
    temp = vpasolve(equations, vars, range, 'random', true);
	sol(i,1) = temp.x;
    sol(i,2) = temp.y;
    sol(i,3) = temp.z;
end
sol
sol = 

(0.910626617256333611769500315510691.78937338274366638823049968448933.96410157213562547241078846668072.36974772245479792091013371601740.330252277545202079089866283982612.29335437682322774312438547086120.910626617256333611769500315510691.78937338274366638823049968448933.96410157213562547241078846668070.910626617256333611769500315510691.78937338274366638823049968448933.96410157213562547241078846668070.910626617256333611769500315510691.78937338274366638823049968448933.9641015721356254724107884666807)

방정식을 플로팅합니다. scatter3을 사용하여 노란색 X 마커로 두 해를 점의 산점도 플롯으로 겹쳐 놓습니다. 플롯을 더 잘 시각화하려면 alpha를 사용하여 두 개의 곡면을 투명하게 만드십시오. caxis를 사용하여 플롯 값의 컬러맵을 스케일링하고, view를 사용하여 원근을 바꿉니다.

vpasolve는 아래와 같이 방정식에 의해 형성된 곡면의 교차점에서 해를 구합니다.

clf
ax = axes;
h = fimplicit3(equations);
h(2).FaceAlpha = 0;
h(3).FaceAlpha = 0;
axis([0 2.5 0 2.5 -20 10])
hold on
scatter3(sol(:,1),sol(:,2),sol(:,3),600,'yellow','X','LineWidth',2)
title('Randomly found solutions in specified search range')
cz = ax.Children;
caxis([0 20])
view(69,28)
hold off