다항식의 실제 근을 구합니다


24

다항식과 한계가 주어지면 한계를 초과하지 않는 절대 오차에 대한 다항식의 모든 근을 찾을 수있는 자체 포함 프로그램을 작성하십시오.

제약

Mathematica와 다른 언어에는 하나의 기호 솔루션이 있으며 지루하다는 것을 알고 있으므로 기본 연산 (더하기, 빼기, 곱하기, 나누기)을 고수해야합니다.

입력 및 출력 형식에는 특정 유연성이 있습니다. stdin 또는 명령 행 인수를 통해 적절한 형식으로 입력 할 수 있습니다. 부동 소수점을 허용하거나 합리적인 숫자를 사용해야 할 수도 있습니다. 경계의 경계 또는 역수를 취할 수 있으며 부동 소수점을 사용하는 경우 경계가 2ulp 이상이라고 가정 할 수 있습니다. 다항식은 단일 계수 목록으로 표현해야하지만 빅 엔디안 또는 리틀 엔디안 일 수 있습니다.

완전한 증거를 인라인으로 제공 할 필요는 없지만 프로그램이 항상 작동하는 이유 (모듈로 수치 문제)를 정당화 할 수 있어야합니다.

프로그램은 근이 반복되는 다항식을 처리해야합니다.

x^2 - 2 = 0 (error bound 0.01)

입력은 예를 들어

-2 0 1 0.01
100 1 0 -2
1/100 ; x^2-2

출력은 예를 들어

-1.41 1.42

하지만

-1.40 1.40

약 0.014의 절대 오차가 있기 때문에 ...

테스트 사례

단순한:

x^2 - 2 = 0 (error bound 0.01)

x^4 + 0.81 x^2 - 0.47 x + 0.06 (error bound 10^-6)

여러 루트 :

x^4 - 8 x^3 + 18 x^2 - 27 (error bound 10^-6)

윌킨슨의 다항식 :

x^20 - 210 x^19 + 20615 x^18 - 1256850 x^17 + 53327946 x^16 -1672280820 x^15 +
    40171771630 x^14 - 756111184500 x^13 + 11310276995381 x^12 - 135585182899530 x^11 +
    1307535010540395 x^10 - 10142299865511450 x^9 + 63030812099294896 x^8 -
    311333643161390640 x^7 + 1206647803780373360 x^6 -3599979517947607200 x^5 +
    8037811822645051776 x^4 - 12870931245150988800 x^3 + 13803759753640704000 x^2 -
    8752948036761600000 x + 2432902008176640000  (error bound 2^-32)

NB이 질문은 약 3 개월 동안 샌드 박스 에있었습니다. 게시하기 전에 개선이 필요하다고 생각되면 Sandbox를 방문하여 Main에 게시 되기 전에 제안 된 다른 질문에 의견을 보내십시오 .



@belisarius, ??
피터 테일러

3
농담으로 의도되었다 :(
Dr. belisarius

나는 이것이 오래된 도전이라는 것을 알고 있으므로 다시 열지 않으려는 경우 대답 할 의무가 없습니다. (ᄀ) 함수를 작성할 수 있습니까, 아니면 전체 프로그램 만 쓸 수 있습니까? (b) 함수를 작성할 수있는 경우, 입력에서 편리한 데이터 유형 (예 : Python fractions.Fraction(합리적 유형))을 사용한다고 가정 할 수 있습니까? (c) 1보다 작은 다항식을 처리해야합니까? (d) 선행 계수가 1이라고 가정 할 수 있습니까?
ELL

(e) 반복 된 뿌리를 가진 다항식과 관련하여, 홀수의 뿌리와 다중도를 구별 할 가치가 있습니다 (테스트 케이스는 홀수의 다중도의 뿌리만을가집니다). 홀수의 다중도의 뿌리는 다루기가 어렵지 않지만 특히 다중의 근을 수치 적으로 올바르게 처리하는 것이 얼마나 확실한지 잘 모르겠습니다. 특히 근이 아닌 근의 값에 대해서만 오차 한계를 지정하기 때문입니다. (...)
ELL

답변:


8

매스 매 티카, 223

r[p_,t_]:=Module[{l},l=Exponent[p[x],x];Re@Select[NestWhile[Table[#[[i]]-p[#[[i]]]/Product[If[i!=j,#[[i]]-#[[j]],1],{j,l}],{i,l}]&,Table[(0.9+0.1*I)^i,{i,l}],2*Max[Table[Abs[#1[[i]]-#2[[i]]],{i,l}]]>t&,2],Abs[Im[#]]<t^.5&]]

이 솔루션은 다항식을 해결하기위한 Durand–Kerner 방법을 구현합니다. Wilkinson의 다항식을 지정된 정밀도로 처리 할 수 ​​없으므로 (아래에 표시된 것처럼) 완벽한 솔루션은 아닙니다. 먼저 내가하고있는 일에 대한 설명 : 수학 형식의 코드

#[[i]]-p[#[[i]]]/Product[If[i!=j,#[[i]]-#[[j]],1],{j,l}]&: 따라서 함수는 각 색인에 i대해 다음 Durand-Kerner 근사값을 계산합니다 . 그런 다음이 줄은 테이블에 캡슐화되고 NestWhile을 사용하여에 의해 생성 된 입력 지점에 적용됩니다 Table[(0.9+0.1*I)^i,{i,l}]. NestWhile의 조건은 한 반복에서 다음 반복으로의 최대 변경 (모든 용어에 대한)이 지정된 정밀도보다 큽니다. 모든 용어가 이보다 작게 변경되면 NestWhile은 끝나고 Re@Select실제 줄에 포함되지 않는 0을 제거합니다.

출력 예 :

> p[x_] := x^2 - 2
> r[p, .01]
{1.41421, -1.41421}

> p[x_] := x^4 - 8 x^3 + 18 x^2 - 27
> r[p, 10^-6]
{2.99999, 3., 3.00001, -1.}

> p[x_] := x^20 - 210 x^19 + ... + 2432902008176640000 (Wilkinson's)
> Sort[r[p, 2^-32]]
{1., 2., 3., 4., 5., 6., 7.00001, 7.99994, 9.00018, 10.0002, 11.0007, \
11.9809, 13.0043, 14.0227, 14.9878, 16.0158, 16.9959, 17.9992, \
19.0001, 20.}

보시다시피, 정도가 높아지면이 방법은 정확한 값을 중심으로 튀어 오르기 시작합니다. 내 코드의 중지 조건을 "한 번의 반복에서 다음 번의 추측으로 엡실론 이상으로 변경되지 않은 것"보다 엄격한 것으로 설정하면 알고리즘이 중지되지 않습니다. Durton-Kerner를 Newton의 방법에 대한 입력으로 사용해야한다고 생각합니까?


Durand-Kerner는 여러 루트에 잠재적 인 문제가 있습니다. (Newton의 방법은별로 도움이되지 않을 수 있습니다-Wilkinson의 다항식은 특별히 조건이 맞지 않도록 선택되었습니다).
피터 테일러

당신은 꽤 정확합니다 : 나는 Wilkinson의 x = 17 근처에서 확대 한 후에 그 행동을 포기했습니다. 그것은 절대 엉망입니다. 정확성을 높이려면 Groebner 기반의 상징적 솔루션을 사용해야 할까 걱정됩니다.
Kaya
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.