一元线性回归计算·Cpp实现

一、直接上代码!

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>

class LinearRegression
{
	private:
		int k;
		double* data_a;
		double* data_b;
		
		double x_average;
		bool x_average_mark;
		double y_average;
		bool y_average_mark;
		double xy_average;
		bool xy_average_mark;
		double xx_average;
		bool xx_average_mark;
		double yy_average;
		bool yy_average_mark;
		
		double a;
		bool a_mark;
		
		double b;
		bool b_mark;
		
		double r;
		bool r_mark; 
		
		double u_a;
		bool u_a_mark;
		double u_b;
		bool u_b_mark;
		double u_c;
		bool u_c_mark;
		double u_d;
		bool u_d_mark;
		
		void cal_x_average();
		void cal_y_average();
		void cal_xy_average();
		void cal_xx_average();
		void cal_yy_average();
		void pri_cal_u_a();
		void pri_cal_u_b();
		void pri_cal_u_c();
		void pri_cal_u_d(); 
		
	public:
		LinearRegression(int p_k);
		~LinearRegression();
		bool accuire_data(std::string& file_name);	
		void reverse_data(std::string choice="a");
		double cal_a();
		double cal_b();
		double cal_r();
		double cal_u_a();
		double cal_u_b();
		double cal_u_c();
		double cal_u_d();
};

int main(int argc,char** argv)
{
	//本程序有两个参数,第一个参数为k,第二个参数为数据文件(txt格式) 
	if (argc!=3)
		return 1;
	std::string length_string=(std::string)argv[1];
	std::string name_string=(std::string)argv[2];
	
	//创建一个自定义的LinearRegression类的对象实例example 
	LinearRegression example(std::stoi(length_string));
	
	//获取数据,调用accuire_data方法 
	example.accuire_data(name_string);
	
	//将因变量组的所有元素取倒数 
	//这个函数用于自变量或因变量组的所有元素取倒数
	//参数为"a",则对自变量组取倒数;参数为"b",则对因变量组取倒数。
	//如果不需要取倒数,直接注释这一行即可。 
	//example.reverse_data("b");
	
	//调用cal_a方法计算a 
	std::cout<<"a:"<<example.cal_a()<<std::endl;
	//调用cal_b方法计算b 
	std::cout<<"b:"<<example.cal_b()<<std::endl;
	//调用cal_r方法计算r
	std::cout<<"r:"<<example.cal_r()<<std::endl;
	//调用cal_u_a方法计算a的A类不确定度 
	std::cout<<"u_a(a):"<<example.cal_u_a()<<std::endl;
	//调用cal_u_b方法计算b的A类不确定度 
	std::cout<<"u_a(b):"<<example.cal_u_b()<<std::endl;
	//调用cal_u_c方法计算a的B类不确定度 
	std::cout<<"u_b(a):"<<example.cal_u_c()<<std::endl;
	//调用cal_u_d方法计算b的B类不确定度 
	std::cout<<"u_b(b):"<<example.cal_u_d()<<std::endl;
	
	//以上7个方法均可以单独使用。
	//我已经把可能存在的问题解决了! 
}

LinearRegression::LinearRegression(int p_k)
{
	k=p_k;
	data_a=new double [k];
	data_b=new double [k];
	x_average_mark=false;
	y_average_mark=false;
	xy_average_mark=false;
	xx_average_mark=false;
	yy_average_mark=false;
	a_mark=false;
	b_mark=false;
	r_mark=false;
	u_a_mark=false;
	u_b_mark=false;
	u_c_mark=false;
	u_d_mark=false;
}

LinearRegression::~LinearRegression()
{
	delete [] data_a;
	delete [] data_b;
} 

bool LinearRegression::accuire_data(std::string& file_name)
{
	using namespace std;
	ifstream file(file_name);
	string double_string;
	char ch;
	int j;
	
	if (file.is_open())
	{
		for (int i=0;i<k;i++)
		{
			j=0;
			double_string="";
			while(1)
			{
				ch=file.get();
				if (ch>='0'&&ch<='9'||ch=='.')
					double_string[j++]=ch;
				else
					break;
			}
			data_a[i]=std::stod(double_string);
		}
		
		for (int i=0;i<k;i++)
		{
			j=0;
			double_string="";
			while(1)
			{
				ch=file.get();
				if (ch>='0'&&ch<='9'||ch=='.')
					double_string[j++]=ch;
				else
					break;
			}
			data_b[i]=std::stod(double_string);
		}
		
		return true;
	}
	else
	{
		return false;
	}
}

void LinearRegression::reverse_data(std::string choice)
{
	if (choice=="a")
		for (int i=0;i<k;i++)
			data_a[i]=1/data_a[i];
	else if (choice=="b")
		for (int i=0;i<k;i++)
			data_b[i]=1/data_b[i];
}

void LinearRegression::cal_x_average()
{
	if (x_average_mark==false)
	{
		double sum=0;
		for (int i=0;i<k;i++)
			sum+=data_a[i];
		x_average=sum/k;
		x_average_mark=true;
	}
}

void LinearRegression::cal_y_average()
{
	if (y_average_mark==false)
	{
		double sum=0;
		for (int i=0;i<k;i++)
			sum+=data_b[i];
		y_average=sum/k;
		y_average_mark=true;
	}
}

void LinearRegression::cal_xy_average()
{
	if (xy_average_mark==false)
	{
		double sum=0;
		for (int i=0;i<k;i++)
			sum+=data_a[i]*data_b[i];
		xy_average=sum/k;
		xy_average_mark=true;
	}
}

void LinearRegression::cal_xx_average()
{
	if (xx_average_mark==false)
	{
		double sum=0;
		for (int i=0;i<k;i++)
			sum+=data_a[i]*data_a[i];
		xx_average=sum/k;
		xx_average_mark=true;
	}
}

void LinearRegression::cal_yy_average()
{
	if (yy_average_mark==false)
	{
		double sum=0;
		for (int i=0;i<k;i++)
			sum+=data_b[i]*data_b[i];
		yy_average=sum/k;
		yy_average_mark=true;
	}
}

double LinearRegression::cal_a()
{
	
	if (a_mark==false)
	{
		this->cal_y_average();
		this->cal_x_average();
		this->cal_b();
		
		a=y_average-b*x_average;
		a_mark=true;
	}
	
	return a;
}

double LinearRegression::cal_b()
{
	
	if (b_mark==false)
	{
		this->cal_x_average();
		this->cal_y_average();
		this->cal_xy_average();
		this->cal_xx_average();
		
		b=(x_average*y_average-xy_average)/(x_average*x_average-xx_average);
		b_mark=true;
	}
	
	return b;
}

double LinearRegression::cal_r()
{
	if (r_mark==false)
	{
		this->cal_x_average();
		this->cal_y_average();
		this->cal_xy_average();
		this->cal_xx_average();
		this->cal_yy_average();
		
		r=(xy_average-x_average*y_average)/sqrt((xx_average-x_average*x_average)*(yy_average-y_average*y_average));
		r_mark=true;
	}
	
	return r;
}


void LinearRegression::pri_cal_u_b()
{
	if (u_b_mark==false)
	{	
		u_b=b*sqrt((1/(r*r)-1)/(k-2));
		u_b_mark=true;
	}	
}

void LinearRegression::pri_cal_u_a()
{
	this->pri_cal_u_b();
	
	if (u_a_mark==false)
	{
		u_a=sqrt(xx_average)*u_b;
		u_a_mark=true;
	}
}

void LinearRegression::pri_cal_u_c()
{
	this->pri_cal_u_d();
	
	if (u_c_mark==false)
	{	
		u_c=sqrt(xx_average)*u_d;
		u_c_mark=true;
	}	
}

void LinearRegression::pri_cal_u_d()
{	
	if (u_d_mark==false)
	{	
		double u_b_y;
		std::cout<<"Please input the type B evaluation of uncertainty of dependent variable --- y:"<<std::endl;
		std::cout<<"(Attention! Do not forget the confidence coefficient)"<<std::endl;
		std::cin>>u_b_y;
		u_d=u_b_y*sqrt(1/(k*(xx_average-x_average*x_average)));
		u_d_mark=true;
	}	
}

double LinearRegression::cal_u_a()
{
	this->pri_cal_u_a();
	return u_a;
}

double LinearRegression::cal_u_b()
{
	this->pri_cal_u_b();
	return u_b; 
}

double LinearRegression::cal_u_c()
{
	this->pri_cal_u_c();
	return u_c;
}

double LinearRegression::cal_u_d()
{
	this->pri_cal_u_d();
	return u_d;
}

二、使用注意事项

1、基本使用方法

复制上面这个代码段到新的cpp文件后编译。

2、C++11标准

由于调用了string库中的std::stod()函数,所以需要以C++11标准对此cpp文件进行编译。

具体方法可以参考:
DEV c++中添加c++11编译环境_devcpp支持c11_中国“名猿”的博客-CSDN博客

3、数据文件

该程序运行依赖数据文件(txt格式), 把数据文件和cpp原文件放在一个文件夹里!

并且,数据文件需要按如下方式处理:
 

假设数据量为k,则需要输入2k组double型数据。数据与数据之间用任意单个空格符/换行符分割!

4、运行参数

本程序有两个参数,第一个参数为k,第二个参数为数据文件(txt格式)。运行参数可以如下输入:

5 test.txt

 其中前者为数据量,后者为数据文件名称。

具体如何添加运行参数,可以参考下面这一篇文章:
关于devc++中程序运行参数的输入问题_如何用dev运行命令行参数_yupl的博客-CSDN博客

又或者,你可以直接用控制台!

5、类方法

一共包含了9个公有类方法。其中第一个方法必须是accuire_data,用于获取数据;第二个方法可以选择按照自身需求对数据取倒数(也可以不执行!看你的需要!)

其他7个方法可以按照任意顺序调用。

三、写在后面

所有的函数和变量都被封装在了LinearRegression类中。欢迎各位大神继承这个类编写更多功能,也欢迎直接大刀阔斧地改写这个类!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值