【发布时间】:2017-07-18 14:53:41
【问题描述】:
(免责声明:我的数学很糟糕,并且来自 JavaScript,因此对于任何不准确之处,我深表歉意,并会尽力纠正它们。)
Rosetta Code 上的example 展示了如何使用 gsl 计算系数。代码如下:
polifitgsl.h:
#ifndef _POLIFITGSL_H
#define _POLIFITGSL_H
#include <gsl/gsl_multifit.h>
#include <stdbool.h>
#include <math.h>
bool polynomialfit(int obs, int degree,
double *dx, double *dy, double *store); /* n, p */
#endif
polifitgsl.cpp:
#include "polifitgsl.h"
bool polynomialfit(int obs, int degree,
double *dx, double *dy, double *store) /* n, p */
{
gsl_multifit_linear_workspace *ws;
gsl_matrix *cov, *X;
gsl_vector *y, *c;
double chisq;
int i, j;
X = gsl_matrix_alloc(obs, degree);
y = gsl_vector_alloc(obs);
c = gsl_vector_alloc(degree);
cov = gsl_matrix_alloc(degree, degree);
for(i=0; i < obs; i++) {
for(j=0; j < degree; j++) {
gsl_matrix_set(X, i, j, pow(dx[i], j));
}
gsl_vector_set(y, i, dy[i]);
}
ws = gsl_multifit_linear_alloc(obs, degree);
gsl_multifit_linear(X, y, c, cov, &chisq, ws);
/* store result ... */
for(i=0; i < degree; i++)
{
store[i] = gsl_vector_get(c, i);
}
gsl_multifit_linear_free(ws);
gsl_matrix_free(X);
gsl_matrix_free(cov);
gsl_vector_free(y);
gsl_vector_free(c);
return true; /* we do not "analyse" the result (cov matrix mainly)
to know if the fit is "good" */
}
main.cpp(请注意,我已将 x any y 的示例编号替换为我自己的):
#include <stdio.h>
#include "polifitgsl.h"
#define NP 11
double x[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
double y[] = {98.02, 98.01, 98.01, 98.02, 97.98, 97.97, 97.96, 97.94, 97.96, 97.96, 97.97, 97.97, 97.94, 97.94, 97.94, 97.92, 97.96, 97.9, 97.85, 97.9};
#define DEGREE 3
double coeff[DEGREE];
int main()
{
int i;
polynomialfit(NP, DEGREE, x, y, coeff);
for(i=0; i < DEGREE; i++) {
printf("%lf\n", coeff[i]);
}
return 0;
}
这是输出:
98.030909
-0.016182
0.000909
所以这给了我系数。但我真正想要的是实际的拟合点。在 JavaScript 中,我使用了regression package 来计算分数:
var regression = require('regression');
var calculateRegression = function(values, degree) {
var data = [];
var regressionOutput;
var valuesCount = values.length;
var i = 0;
// Format the data in a way the regression library expects.
for (i = 0; i < valuesCount; i++) {
data[i] = [i, values[i]];
}
// Use the library to calculate the regression.
regressionOutput = regression('polynomial', data, degree);
return regressionOutput;
};
var y = [98.02, 98.01, 98.01, 98.02, 97.98, 97.97, 97.96, 97.94, 97.96, 97.96, 97.97, 97.97, 97.94, 97.94, 97.94, 97.92, 97.96, 97.9, 97.85, 97.9];
console.log(calculateRegression(y, 3));
产生:
{ equation:
[ 98.02987916431594,
-0.017378390369880512,
0.0015748071645344357,
-0.00005721503635571101 ],
points:
[ [ 0, 98.02987916431594 ],
[ 1, 98.01401836607424 ],
[ 2, 98.00096389194348 ],
[ 3, 97.9903724517055 ],
[ 4, 97.98190075514219 ],
[ 5, 97.97520551203543 ],
[ 6, 97.96994343216707 ],
[ 7, 97.96577122531896 ],
[ 8, 97.96234560127297 ],
[ 9, 97.959323269811 ],
[ 10, 97.95636094071487 ],
[ 11, 97.95311532376647 ],
[ 12, 97.94924312874768 ],
[ 13, 97.94440106544033 ],
[ 14, 97.93824584362629 ],
[ 15, 97.93043417308745 ],
[ 16, 97.92062276360569 ],
[ 17, 97.90846832496283 ],
[ 18, 97.89362756694074 ],
[ 19, 97.87575719932133 ] ],
string: 'y = 0x^3 + 0x^2 + -0.02x + 98.03' }
(请注意,JavaScript 中存在浮点问题,因此数字并不完全准确。)
points 这是我想要使用 gsl 生成的。有什么办法可以做到吗?
【问题讨论】:
-
gsl确实不需要生成积分。如果您上面的等式是y = x^3 + x^2 - 0.2x + 98.03,那么对于任何x,您计算一个对应的值y,构成您的(x, y)点。您只需要一个简单的double y; for (x = 0; x < 20; x++) y = x*x*x + x*x -.02*x + 98.03;即可生成上面列出的点。完全没有gsl影响。 -
当然——非常有意义。我怎么没有意识到这一点:) 谢谢!
-
嗯,其实我还是有点迷茫。当我运行 gsl 示例时,这就是我得到的所有输出:98.030909、-0.016182 和 0.000909。我究竟如何从中建立一个方程?
-
乍得,如果你说的是曲线拟合中使用的向量和协方差矩阵中的点,可以使用
gsl_vector_get和gsl_matrix_get(参见:gsl multifit example)否则,如果您只是在谈论x值范围内任何点的点,那么只需使用找到系数的多项式方程即可。您在上面的示例中显示的似乎是曲线拟合中使用的点。
标签: c polynomial-math gsl