# Horner’s method When evaluating a polynomial function (1) in a computer program, the naivest way usually result in more computation complexcity. In order to speed up the process, Horner's scheme were used. \begin{equation} P(x) = a_0 + a_1 x + a_2 x^2 + ... + a_n x^n \tag{1} \end{equation} Rather than direct evaluating (1), Horner's scheme change (1) into (2) which can give the same result but a more efficient way. Naive way of evaluating polynomail requires at most $n$ additions and $(n^2+n)/2$ multiplications while Horner's scheme only require $n$ additions and $n$ multiplications. \begin{equation} P(x) = a_0 + x\left(a_1 + x\left(a_2 + x\left(a_3+...+x\left(a_{n-1}+xa_n\right)\right)\right)\right) \tag{2} \end{equation} Following program first computing the coefficient $a_j$, then I generate a random number using subroutine RANDOM\_NUMBER. Finally, I use another intrinsic function CPU\_TIME to measure time it takes for two different approach to evaluating the polynomial ($10^5$ times). ## Code ```fortran !======================================================== ! Purpose: Camparing Horner's scheme with naive way ! ! Methods: Horner's Method ! ! Date Programer Description of change ! ==== ========= ===================== ! 8/13/20 MorrisH Original Code !======================================================== PROGRAM MAIN IMPLICIT NONE REAL(8) :: a(100), start, finish, x REAL(8) :: NAIVE, HORNER INTEGER :: i, CALL RANDOM_SEED() CALL RANDOM_NUMBER(x) open(99, file='naive.dat', status='unknown') open(66, file='horner.dat', status='unknown') do i = 1, 100, 2 a(i) = 1.d0 / DBLE(i) end do do i = 2, 100, 2 a(i) = -1.d0 / DBLE(i) end do CALL CPU_TIME(start) do i = 1, 100000 ans = NAIVE(a, x) end do CALL CPU_TIME(finish) ! print *, ans ! print '("Naive method cost : ", f7.5, "seconds")', finish-start write(99, *) finish-start, ans CALL CPU_TIME(start) do i = 1, 100000 ans = HORNER(a, x) end do CALL CPU_TIME(finish) ! print *, ans ! print '("Horner method cost : ", f7.5, "seconds")', finish-start write(66, *) finish-start, ans END PROGRAM MAIN DOUBLE PRECISION FUNCTION NAIVE(a, x) IMPLICIT NONE REAL(8) :: a(100), x INTEGER :: i NAIVE = 0.d0 do i = 1, 100 NAIVE = NAIVE + a(i) * x ** DBLE(i) end do END FUNCTION NAIVE DOUBLE PRECISION FUNCTION HORNER(a, x) IMPLICIT NONE REAL(8) :: a(100), x INTEGER :: i HORNER = x * a(100) do i = 100, 2, -1 HORNER = (HORNER + a(i-1)) * x end do END FUNCTION HORNER ``` ## Result I calculate the time it takes for both method to preform $10^5$ times, and divide the time it takes using naive method by the time of evaluating using Horner's method. Naive way cost roughly 7 times longer to calculate in this particular example than Horner's method did. ![](https://i.imgur.com/BpicvzI.png) \begin{equation} P(x) = \dfrac{x}{1} + \dfrac{x^2}{2} + ... + \dfrac{x^n}{n} = x\left(\dfrac{1}{1}+x\left(\dfrac{1}{2}+x\left(\dfrac{1}{3}+...+x\left(\dfrac{1}{n-1}+x\dfrac{1}{n}\right)\right)\right)\right) \tag{3} \end{equation} For meausering the accuracy, I evaluating (3) from $x=-100$ to $x=100$ using two method. But it seems that the accuracy are roughly the same in this particular example. ![](https://i.imgur.com/mdwd8aT.png)