Tutorial :How to get value prediction from Polynomial curve?



Question:

Okay, so maths isn't my strong point!

I have this data, I i used zunzun.com to create a User Defined Polynomial curve for my data, which came out as y = a + bx1 + cx2 + dx3 + ex4 + fx5

However, when I use the code suggested:

  double a = -4.2294409347240979E+01;    double b = 5.5946102161174718E+00;    double c = -1.3446057748924720E-01;    double d = 1.5448461146899649E-03;    double e = -8.2537158069276241E-06;    double f = 1.7176546321558128E-08;      temp = f;    temp = temp * x_in + e;    temp = temp * x_in + d;    temp = temp * x_in + c;    temp = temp * x_in + b;    temp = temp * x_in + a;    return temp;  

It gives me the 'sum of squared absolute error'? Say for X value 94, I should get a value of about 60.3, but this code gives me -46.152. I realise I am being stupid and am obviously missing an equation on the end. But can anyone help me predict my Y value from my X with this forumla? The graph fits its really well and would be great to not have to use a lookup table.

Many Thanks!

X Y
180 200
178 190
176 180
174 170
170 160
168 150
164 140
160 130
154 120
149 110
142 100
134 90
122 80
110 70
92 60
66 50
30 40

Thanks everyone! Code is working now: http://img72.imageshack.us/img72/3705/ps3lrftest.png


Solution:1

Excuse my rounding but you're implementing;

Y = a + bx + cx^2 + dx^3 + ex^4 + f*x^5

x = 94
x^2 == xx = 8836
x^3 == x
xx = 830584
x^4 == x
xxx = 78074896
x^5 == xxxxx = 7339040224

A ~ -42.29440934
B ~ 05.59461021
C ~ -0.134460577
D ~ 0.001544846
E ~ -0.000008253
F ~ 0.000000017

Y = -42.29440934 + 05.59461021*94 + -0.134460577*8836 + 0.001544846*830584 + -0.000008253*78074896 + 0.000000017*7339040224

Y = -42.29440934 + 525.89335974 - 1188.093658372 + 1283.124370064 - 644.352116688 + 124.763683808

Y = 59.041229212

Not quite your answer but with sufficient accuracy you should be good.


Solution:2

Whatever temp computes, it's not the y value. But you've figured out as much :) This should do?

def y(x, coefficients):      result = 0      xpower = 1          for coeff in coefficients:          result += xpower*coeff          xpower *= x          return result  


Solution:3

I don't know what is wrong with your implementation, but the code you gave is correct. You can write (using second degree polynomial for simplicity):

y = a + b*x + c*x^2  

as

y = a + (b + (c)*x)*x  

or, equivalently:

temp = c  temp = temp*x + b  temp = temp*x + a  y = temp  

You just assign the expression inside the parenthesis to temp from the innermost one and expanding outwards.

This is the same format that you've shown above. Just use 6 coefficients instead of 3. For more details on this polynomial evaluation method, you can read Horner's Scheme in Wikipedia.

To validate, using Python:

>>> a = -4.2294409347240979E+01  >>> b = 5.5946102161174718E+00  >>> c = -1.3446057748924720E-01  >>> d = 1.5448461146899649E-03  >>> e = -8.2537158069276241E-06  >>> f = 1.7176546321558128E-08  >>> def test(x):  ...     t = f  ...     t = t*x + e  ...     t = t*x + d  ...     t = t*x + c  ...     t = t*x + b  ...     t = t*x + a  ...     return t  ...  >>> test(94)  60.281114720346885  


Solution:4

Here's how I'd write it in Java:

/**   * Polynomial   * User: Michael   * Date: Jul 27, 2010   * Time: 7:15:41 PM   */  public class Polynomial  {      private double [] coeff;        public Polynomial(double[] coeff)      {          if ((coeff == null) || (coeff.length == 0))              throw new IllegalArgumentException("coefficient array cannot be null or empty");            this.coeff = new double [coeff.length];          System.arraycopy(coeff, 0, this.coeff, 0, coeff.length);      }        public double eval(double x)      {          int numTerms = coeff.length;          double value = coeff[numTerms-1];            for (int i = (numTerms-2); i >= 0; --i)          {              value += value*x + this.coeff[i];          }            return value;      }        @Override      public String toString()      {          StringBuilder builder = new StringBuilder(128);            for (int i = 0; i < (this.coeff.length-1); ++i)          {              builder.append("a[").append(i).append("]=").append(this.coeff[i]).append(",");          }            builder.append("a[").append(this.coeff.length-1).append("]=").append(this.coeff[this.coeff.length-1]);            return builder.toString();      }  }  

Here's how I'd test it:

import org.junit.Test;    import static org.junit.Assert.assertEquals;    /**   * PolynomialTest   * User: Michael   * Date: Jul 27, 2010   * Time: 7:26:15 PM   */  public class PolynomialTest  {      private static final double [] a =      {          -4.2294409347240979E+01,           5.5946102161174718E+00,          -1.3446057748924720E-01,           1.5448461146899649E-03,          -8.2537158069276241E-06,           1.7176546321558128E-08,      };        private Polynomial p = new Polynomial(a);        @Test      public void testEval()      {          double x = 94.0;          double expected = 60.83781703621137;          double actual = p.eval(x);            assertEquals(expected, actual, 1.0e-3);      }        @Test      public void testToString()      {          String expected = "a[0]=-42.29440934724098,a[1]=5.594610216117472,a[2]=-0.1344605774892472,a[3]=0.0015448461146899649,a[4]=-8.253715806927624E-6,a[5]=1.7176546321558128E-8";          String actual = p.toString();            assertEquals(expected, actual);      }  }  


Solution:5

Hyperbolic equations in general fit this data well. My personal recommendation is to use

"Simple Equation 21"

http://zunzun.com/Equation/2/Simple/Simple%20Equation%2021/

instead of a polynomial. But if what you have works, there is no particular reason to change it.

James Phillips zunzun@zunzun.com


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »