-
Notifications
You must be signed in to change notification settings - Fork 21
/
findq.Rmd
46 lines (39 loc) · 1.23 KB
/
findq.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
---
title: "Polynomial roots in (0,1)"
author: "Douglas Bates"
date: "09/05/2014"
output: html_document
---
# Finding roots in the unit interval
Instead of using the `polyroot` function I would use the `polynom` package, written by Bill Venables and now maintained by Kurt Hornik and Martin Maechler.
```{r library}
library(polynom)
(p <- polynomial(c(0.1, 0.3, 0.4, 0.0,0.2)))
```
To scale the coefficients so that they add to 1, you don't compare with 1. You use
```{r compare}
all.equal(sum(as.vector(p)),1)
```
In general you should use tolerances based on the "relative machine precision", which is available as
```{r eps}
.Machine$double.eps
```
For the general function you have
```{r findq}
findq <- function(pvector) {
stopifnot(is.vector(pvector,"numeric"),
all(pvector >= 0.))
if (!isTRUE(all.equal(sum(pvector),1))) {
## do something here
}
roots <- solve(polynomial(pvector)-polynomial(c(0,1)))
realroots <- Re(roots[which(abs(Im(roots)) < 1e3*.Machine$double.eps)])
eligible <- realroots[0 <= realroots & realroots < 1]
if (length(eligible) <= 1L) return(eligible)
eligible[which.min(abs(eligible-0.5))]
}
```
Check out the function
```{r check}
findq(c(0.1, 0.3, 0.4, 0, 0.2))
```