[R] solving cubic/quartic equations non-iteratively -- comparisons
Larry Hotchkiss
larryh at udel.edu
Fri Jan 8 23:07:25 CET 2010
Hi,
I'm responding to a post about finding roots of a cubic or quartic equation non-iteratively. One obviously could create functions using the explicit algebraic solutions. One post on the subject noted that the square-roots in those solutions also require iteration, and one post claimed iterative solutions are more accurate than the explicit solutions.
This post, however, is about comparative accuracy of (1) the R solve functionused in the included post, (2) the R polyroot function, (3) the Matlab roots function, (4) the SAS IML polyroot function. I tried the posted polynomial:
-8 + 14*x - 7*x^2 + x^3 = 0
and a repeating-roots example:
8 - 36*x + 54*x^2 - 27*x^3 = 0
I used Mathematica solutions as the reference:
(* Posted example *)
Roots[-8 + 14 x - 7 x^2 + x^3 == 0, x]
x == 1 || x == 2 || x == 4
(* Repeating-roots example *)
Roots[8 - 36 x + 54 x^2 - 27 x^3 == 0, x]
x == 2/3 || x == 2/3 || x == 2/3
The results indicate that the R polyroot function is the most accurate for these examples. The R solve function is quite inaccurate for the repeating-roots example. It appears to be single-precision arithmetic on the real and imaginary parts. The same appears to be true for the Matlab function roots. SAS IML polyroot function appears to use double-precision calculations but was not nearly as accurate as the R polyroot function for the repeating-roots example.
The syntax and output for these examples are as follows:
# ------------------------------------------------------------------------- #
Mathematica:
(* Posted example *)
Roots[-8 + 14 x - 7 x^2 + x^3 == 0, x]
x == 1 || x == 2 || x == 4
(* Repeating-roots example *)
Roots[8 - 36 x + 54 x^2 - 27 x^3 == 0, x]
x == 2/3 || x == 2/3 || x == 2/3
# ------------------------------------------------------------------------- #
R:
> options(digits=16)
> library(polynom)
# Posted example
> p <- polynomial(c(-8,14,-7,1))
> solve(p)
[1] 0.999999999999999 2.000000000000002 3.999999999999997
>
> polyroot(c(-8,14,-7,1))
[1] 1-0i 2+0i 4-0i
>
# Repeating-roots example
> lp <- polynomial(c(8,-36, 54, -27))
> solve(lp)
[1] 0.6666648437558125-0.000003157332198i 0.6666648437558125+0.000003157332198i
[3] 0.6666703124883749+0.000000000000000i
> polyroot(lp)
[1] 6.666666666666670e-01+2e-16i 6.666666666666666e-01-8e-17i
[3] 6.666666666666664e-01-1e-16i
# ------------------------------------------------------------------------- #
Matlab:
>> format long
>> format compact
% Note: Matlab order of polynomial is reverse of R
% Posted example
>> p = [-8,14,-7,1]; p = p(4:(-1):1)
p =
1 -7 14 -8
>> roots(p)
ans =
4.000000000000000
2.000000000000004
0.999999999999999
% Repeating-roots example
>> lp = [8,-36, 54, -27]; lp = lp(4:(-1):1)
lp =
-27 54 -36 8
>> roots(lp)
ans =
0.666669450738337 + 0.000004822149713i
0.666669450738337 - 0.000004822149713i
0.666661098523329
# ------------------------------------------------------------------------- #
SAS proc IML:
proc IML;
* Note: SAS polyroot also uses high-to-low order of the polynomial, reverse
of R fuctions. *;
* Posted example *;
p = {-8 14 -7 1}; p = p[4:1];
rts = polyroot(p);
print p rts[format=19.16];
* Repeating-roots example *;
lp = {8 -36 54 -27}; lp = lp[4:1];
rts = polyroot(lp);
print lp rts[format=19.16];
quit;
* Output;
p rts
1 1.0000000000001500 0.0000000000000000
-7 1.9999999999997700 0.0000000000000000
14 4.0000000000000700 0.0000000000000000
-8
lp rts
-27 0.6666666666666700 0.0000000000000000
54 0.6666666526177100 0.0000000000000000
-36 0.6666666807156100 0.0000000000000000
8
# ------------------------------------------------------------------------- #
Larry Hotchkiss
--------------------------------------------------------------------------------------
Message: 7
Date: Wed, 6 Jan 2010 13:03:14 +0100
From: "Kasper Kristensen" <kkr at aqua.dtu.dk>
Subject: Re: [R] solving cubic/quartic equations non-iteratively
To: <s02mjtj at math.ku.dk>
Cc: r-help at r-project.org
Message-ID:
<88431FCDD055A44BA5EEE1EC14E7E151143E05 at lu-mail-san.dfu.local>
Content-Type: text/plain; charset="iso-8859-1"
Try,
library(polynom)
p <- polynomial(c(-8,14,-7,1))
solve(p)
Kasper
More information about the R-help
mailing list