Precision and rounding errors
Sep 26, 2016 at 2:25am UTC
I wrote some code that will fit data from an ascii file to a polynomial. Ultimately, I will add regression (I've begun, and it is commented out in the below code). This is all to be incorporated into a much larger scientific program later. For now, my problem is this: my polynomial coefficients which are the current output do not match what I've calculated via matrices in wxMaxima. How can I increase accuracy and/or reduce rounding error? I'm still pretty new to c++.
Program output:
1 2 3 4 5 6 7
beta
231.165
-438.513
274.387
-75.3077
9.73383
-0.464325
wxMaxima solution:
1 2 3 4 5 6
226.8797363317376
−430.0542771046293
268.8091043714023
−73.70060682268274
9.523984400796692
−0.45415109784472
Input file data.dat:
1 2 3 4 5 6 7
1 1
2.5 8
3 27
4 64
5.1 125
6 216
7 343
Clearly, this would fit best to a 3rd order polynomial, but right now, I'm testing precision, so I want my result to match that of Maxima. Here is the code:
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
#include <iostream>
#include <fstream>
#include <istream>
#include <vector>
#include <stdio.h>
#include <cmath>
#include <string>
#include <sstream>
#include "../headers/tnt_array1d.h"
#include "../headers/tnt_array2d.h"
#include "../headers/jama_lu.h"
using namespace TNT;
using namespace JAMA;
using namespace std;
int poly=5;
int num_rows;
Array2D<long double > TX(poly+1,num_rows);
Array1D<long double > beta(poly+1);
Array1D<long double > Xbeta()
{
LU<long double > lu(TX);
return lu.solve(beta);
}
int main()
{
// cout.precision(8);
// cout.setf(ios::fixed);
vector <long double > Tsigma;
vector <long double > sigma;
num_rows = 0;
ifstream fin("data.dat" );
vector<vector <long double > > allData;
string line;
while (getline(fin,line))
{
vector<long double > lineData;
long double val;
istringstream lineStream(line);
while (lineStream >> val)
{
lineData.push_back(val);
}
allData.push_back(lineData);
++num_rows;
}
for (int i=0; i<num_rows; i++)
{
Tsigma.push_back(allData[i][0]);
sigma.push_back(allData[i][1]);
// cout << Tsigma[i] << " " << sigma[i] << endl;
}
Array1D<long double > Y(num_rows,1);
for (int i = 0; i < num_rows; i++)
{
Y[i] = sigma[i];
}
Array2D <long double > X(num_rows,poly+1);
for (int i = 0; i < num_rows; i++)
{
for (int j = 0; j <= poly; j++)
{
X[i][j] = pow(Tsigma[i],j);
}
}
LU<long double > lu(X);
Array1D<long double > beta(poly+1,1);
beta = lu.solve(Y);
/* cout << "test2" << endl;
cout << num_rows << endl;
Array2D<long double> TX(poly+1,num_rows);
for (int i = 0; i < num_rows; i++)
{
for (int j = 0; j < poly+1; j++)
{
TX[j][i] = X[i][j];
}
}
cout << "TX" << endl;
cout << TX << endl;
cout << "test3" << endl;
Array1D<long double> epsilon(poly+1);
Array1D<long double> Xbeta_var = Xbeta();
cout << "Xbeta" << endl;
cout << Xbeta_var << endl;
cout << "epsilon" << endl;
for (int i = 0; i < num_rows; i++)
{
epsilon[i] = Y[i] - Xbeta_var[i];
}
cout << epsilon << endl;
*/
cout << "beta" << endl;
for (int i = 0; i < poly+1; i++)
{
cout << beta[i] << endl;
}
return 0;
}
Why doesn't my beta value match that of the calculated value in Maxima? How can I increase precision and/or reduce rounding errors? Any help would be greatly appreciated.
Last edited on Sep 26, 2016 at 8:23am UTC
Sep 26, 2016 at 9:11am UTC
Using a library called Eigen seemed to do the trick. Here is the code that gives high accuracy, in case you ever want to fit an x, y data file to a polynomial. However, if your data file has any blank x or y values or you have a blank line (including at the end of the file), then the program will crash.
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#include <iostream>
#include <fstream>
#include <istream>
#include <vector>
#include <stdio.h>
#include <cmath>
#include <string>
#include <sstream>
#include "../headers/Eigen/Dense"
#include "../headers/Eigen/src/LU/Inverse.h"
using namespace std;
using namespace Eigen;
int poly=6;
int num_rows;
int main()
{
cout.precision(8);
cout.setf(ios::fixed);
vector <long double > Tsigma;
vector <long double > sigma;
num_rows = 0;
ifstream fin("data.dat" );
vector<vector <long double > > allData;
string line;
while (getline(fin,line))
{
vector<long double > lineData;
long double val;
istringstream lineStream(line);
while (lineStream >> val)
{
lineData.push_back(val);
}
allData.push_back(lineData);
++num_rows;
}
for (int i=0; i<num_rows; i++)
{
Tsigma.push_back(allData[i][0]);
sigma.push_back(allData[i][1]);
}
MatrixXd Y(num_rows,1);
for (int i = 0; i < num_rows; i++)
{
Y(i) = sigma[i];
}
MatrixXd X(num_rows,poly+1);
for (int i = 0; i < num_rows; i++)
{
for (int j = 0; j <= poly; j++)
{
X(i,j) = pow(Tsigma[i],j);
}
}
MatrixXd TXX(poly+1,num_rows);
TXX = X.transpose()*X;
MatrixXd TXY(poly+1,1);
TXY = X.transpose()*Y;
MatrixXd beta(poly+1,1);
beta = TXX.inverse()*TXY;
cout << "beta\n" << scientific;
cout << beta << endl;
return 0;
}
Last edited on Sep 26, 2016 at 5:57pm UTC
Topic archived. No new replies allowed.