安卓实现对一组数据进行曲线的拟合

项目需求对每一组数据进行曲线的拟合,拟合成对数,指数,一次线性或者二次线性中最符合要求的一条曲线

下面是工具类:

 

public class MathResult {

//线性公式y=ax+b

public static Object[] lineFitting(double x[], double y[]) { //分别为公式,R的平方值

int size = x.length;

double xmean = 0.0;

double ymean = 0.0;

double xNum = 0.0;

double yNum = 0.0;

double xyNum = 0;

double xNum2 = 0;

double yNum2 = 0;

double rss = 0;

double tss = 0;

double result[] = new double[6];

for (int i = 0; i < size; i++) {

xmean += x[i];

ymean += y[i];

xNum2 += x[i] * x[i];

yNum2 += y[i] * y[i];

xyNum += x[i] * y[i];

}

xNum = xmean;

yNum = ymean;

xmean /= size;

ymean /= size;

double sumx2 = 0.0f;

double sumxy = 0.0f;

for (int i = 0; i < size; i++) {

sumx2 += (x[i] - xmean) * (x[i] - xmean);

sumxy += (y[i] - ymean) * (x[i] - xmean);

}

double b = sumxy / sumx2;

double a = ymean - b * xmean;

result[0] = a;

result[1] = b;

double correlation = (xyNum - xNum * yNum / size) / Math.sqrt((xNum2 - xNum * xNum / size)

* (yNum2 - yNum * yNum / size));

LogUtils.e("相关系数:" + correlation);

result[2] = correlation;

for (int i = 0; i < size; i++) {

rss += (y[i] - (a + b * x[i])) * (y[i] - (a + b * x[i]));

tss += (y[i] - ymean) * (y[i] - ymean);

}

double r2 = 1 - (rss / (size - 1 - 1)) / (tss / (size - 1));

result[3] = r2;

result[4] = x.length;

result[5] = x.length - 1 - 1;

double format = format(result[0], 4);

String s = "";

if (format >= 0) {

s = " +" + format;

} else {

s = " -" + format;

}

// TODO: 2017/12/20 线性计算拟合优度的方法

double xsum = 0d;

for (int i = 0; i < x.length; i++) {

xsum += x[i];

}

double xavg = xsum / x.length;//x的平均值

double x2 = 0d;

for (int i = 0; i < x.length; i++) {

x2 += ((x[i] - xavg) * (x[i] - xavg));

}

double xrange = Math.sqrt(x2 / x.length);//x的标准差

double ysum = 0d;

for (int i = 0; i < y.length; i++) {

ysum += y[i];

}

double yavg = ysum / y.length;//y的平均值

double y2 = 0d;

for (int i = 0; i < y.length; i++) {

y2 += ((y[i] - yavg) * (y[i] - yavg));

}

double yrange = Math.sqrt(y2 / y.length);//y的标准差

double ori = 0d;

for (int i = 0; i < x.length; i++) {

ori += (((x[i] - xavg) / xrange) * ((y[i] - yavg) / yrange));

}

double R2 = format(Math.pow(ori / x.length, 2), 4);

LogUtils.e("拟合优度R的平方为" + R2);

LogUtils.e("公式:" + "y=" + format(result[1], 4) + "* X" + s);

return new Object[]{"Y=" + format(result[1], 4) + "* X " +

s, R2};

}

//

//多项式y=ax的平方+bx+c

// TODO: 2017/12/18 n表示多项式的次数,我们只需考虑到2次

public static Object[] dxsFitting(double x[], double y[], int n) {

double result[] = new double[n + 4];

WeightedObservedPoints obs = new WeightedObservedPoints();

for (int i = 0; i < x.length; i++) {

obs.add(x[i], y[i]);

}

final PolynomialCurveFitter fitter = PolynomialCurveFitter.create(n);

final double[] coeff = fitter.fit(obs.toList());

for (int i = 0; i < coeff.length; i++) {

result[i] = coeff[i];

}

double s = getDxsR(x, y, coeff, 5);

result[n + 1] = x.length;

result[n + 2] = x.length - n - 1;

result[n + 3] = s;

String a1 = "";

String a2 = "";

String a3 = "";

a1 = "Y= " + format(result[2], 4) + "X^2";

if (format(result[1], 4) < 0) {

a2 = " -" + format(result[1], 4) + "* X";

} else {

a2 = " +" + format(result[1], 4) + " * X";

}

if (format(result[0], 4) < 0) {

a3 = " -" + format(result[0], 4);

} else {

a3 = " +" + format(result[0], 4);

}

LogUtils.e("公式:" + a1 + a2 + a3);

// TODO: 2017/12/18 计算R的平方

double ysum = 0d;

for (int i = 0; i < y.length; i++) {

ysum += y[i];

}

double yavg = ysum / y.length;//y的平均值

double sss = 0d;

for (int i = 0; i < x.length; i++) {

sss += Math.pow(y[i] - ((format(result[2], 4) * Math.pow(x[i], 2)) +

(format(result[1], 4) * x[i]) + format(result[0], 4)), 2);

}

double ssreg = 0d;

for (int i = 0; i < x.length; i++) {

ssreg += (y[i] - yavg) * (y[i] - yavg);

}

double R2 = format((1 - sss / ssreg), 4);

LogUtils.e("拟合优度R的平方为===" + R2); //拟合优度

return new Object[]{a1 + a2 + a3, R2};

}

// TODO: 2017/12/20 对数的拟合曲线

// TODO: 2017/12/14 0014 y=a+b*ln(x)

public static Object[] logFitting(double x[], double y[]) {

double yem = 0.0;

double y1 = 0.0;

double xem = 0.0;

double x1 = 0.0;

double x2 = 0.0;

double x3 = 0.0;

double avgx = 0.0;

double avgy = 0.0;

double dxy = 0.0;

double dx2 = 0.0;

double dy2 = 0.0;

double y2 = 0.0;

for (int i = 0; i < y.length; i++) {

yem += y[i];

}

avgy = (yem) / y.length;

for (int i = 0; i < y.length; i++) {

y2 += (y[i] - avgy);

}

for (int i = 0; i < y.length; i++) {

y1 += y[i] * Math.log(x[i]);

}

for (int i = 0; i < x.length; i++) {

xem += x[i];

}

avgx = (xem) / x.length;

for (int i = 0; i < x.length; i++) {

x1 += Math.log(x[i]);

}

for (int i = 0; i < x.length; i++) {

x2 += Math.log((x[i])) * Math.log((x[i]));

}

for (int i = 0; i < x.length; i++) {

if (i == 0) {

x3 = Math.log(x[i]);

} else {

x3 *= Math.log(x[i]);

}

}

for (int i = 0; i < x.length; i++) {

dxy += (x[i] - avgx) * (y[i] - avgy);

}

for (int i = 0; i < x.length; i++) {

dx2 += (x[i] - avgx) * (x[i] - avgx);

}

for (int i = 0; i < y.length; i++) {

dy2 += (y[i] - avgy) * (y[i] - avgy);

}

double A = format((((yem - ((x.length * y1 - yem * x1) / (x.length * x2 - x1 * x1)) * x1))) / x.length, 4);

double B = format(((x.length * y1 - yem * x1) / (x.length * x2 - x1 * x1)), 4);

LogUtils.e("计算的结果为b=" + B);

LogUtils.e("计算结果为a=" + A);

String fb = "";

if (B >= 0) {

fb = "+" + B + "";

} else {

fb = "-" + B;

}

LogUtils.e("公式: Y= " + A + fb + "*lnX");

// TODO: 2017/12/18 计算R的平方

double ysum = 0d;

for (int i = 0; i < y.length; i++) {

ysum += y[i];

}

double yavg = ysum / y.length;//y的平均值

double sss = 0d;

for (int i = 0; i < x.length; i++) {

sss += Math.pow(y[i] - (A + B * Math.log(x[i])), 2);

}

double ssreg = 0d;

for (int i = 0; i < x.length; i++) {

ssreg += (y[i] - yavg) * (y[i] - yavg);

}

double R2 = format((1 - sss / ssreg), 4);

LogUtils.e("拟合优度R的平方为===" + R2); //拟合优度

return new Object[]{"Y= " + A + fb + "*lnX", R2};

}

// TODO: 2017/12/20 计算指数

// TODO: 2017/12/20 y = b*exp(ax)

public static Object[] expFitting(double x[], double y[]) {

double[] oriY = new double[y.length];

for (int i = 0; i < y.length; i++) {

oriY[i] = y[i];

}

int size = x.length;

double xmean = 0.0;

double ymean = 0.0;

double rss = 0;

double tss = 0;

double result[] = new double[5];

for (int i = 0; i < size; i++) {

xmean += x[i];

y[i] = Math.log(y[i]);

ymean += y[i];

}

xmean /= size;

ymean /= size;

double sumx2 = 0.0f;

double sumxy = 0.0f;

for (int i = 0; i < size; i++) {

sumx2 += (x[i] - xmean) * (x[i] - xmean);

sumxy += (y[i] - ymean) * (x[i] - xmean);

}

double b = sumxy / sumx2;

double a = ymean - b * xmean;

for (int i = 0; i < size; i++) {

rss += (y[i] - (a + b * x[i])) * (y[i] - (a + b * x[i]));

tss += (y[i] - ymean) * (y[i] - ymean);

}

double r2 = 1 - (rss / (size - 1 - 1)) / (tss / (size - 1));

a = Math.exp(a);

result[0] = a;

result[1] = b;

result[2] = x.length;

result[3] = x.length - 2;

result[4] = r2;

double B = format(result[1], 4);

double A = format(result[0], 4);

LogUtils.e("公式:" + "Y= " + A + "*e^(" + B + "*X)");

// TODO: 2017/12/18 计算R的平方

double ysum = 0d;

for (int i = 0; i < oriY.length; i++) {

ysum += oriY[i];

}

double yavg = ysum / oriY.length;//y的平均值

double sss = 0d;

for (int i = 0; i < x.length; i++) {

sss += Math.pow((oriY[i] - (A * (Math.exp((B * x[i]))))), 2);

}

double ssreg = 0d;

for (int i = 0; i < x.length; i++) {

ssreg += (oriY[i] - yavg) * (oriY[i] - yavg);

}

double R2 = format((1 - sss / ssreg), 4);

LogUtils.e("拟合优度R的平方为===" + R2); //拟合优度

return new Object[]{"Y= " + A + "*e^(" + B + "*X)", R2};

}

/**

* 获得决定系数

*

* @param coeff

* @return

*/

private static double getDxsR(double x[], double y[], double coeff[], int n) {

int size = x.length;

double ymean = 0.0;

double rss = 0;

double tss = 0;

for (int i = 0; i < size; i++) {

ymean += y[i];

}

ymean /= size;

for (int i = 0; i < size; i++) {

rss += (y[i] - getDxsValueByX(x[i], coeff)) * (y[i] - getDxsValueByX(x[i], coeff));

tss += (y[i] - ymean) * (y[i] - ymean);

}

double r2 = 1 - (rss / (size - n - 1)) / (tss / (size - 1));

return r2;

}

/**

* 通过X获得Y的值

*

* @param x

* @param coeff

* @return

*/

private static double getDxsValueByX(double x, double coeff[]) {

int size = coeff.length;

double result = coeff[0];

for (int i = 1; i < size; i++) {

result += coeff[i] * Math.pow(x, i);

}

return result;

}

//四舍五入

public static double format(double d, int index) {

BigDecimal bd = new BigDecimal(d);

return bd.setScale(index, BigDecimal.ROUND_HALF_UP).doubleValue();

}

}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值