C++读取大型矩阵问题


之前写了个opencv读取大矩阵的问题,这次遇到一个更大的矩阵,不想用opencv格式化读文件,故直接采用c++读取。

首先c++读取文件的几种方式可以参考“探寻C++最快的读取文件的方案”(1)一文,而其中提到的内存映射方法可以参考“windows笔记-内存映射文件”(2)一文。

输入对象是一个50×71028的浮点数矩阵,保存为.txt文件,共55mb,单纯采用fstream格式化读取需要1分钟,而采用scanf读入需要15秒。故决定采取文(1)中介绍的读入整个文件再处理的方法,代码如下:

int main()
{
	int start = clock();	
    readdata1();
    printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC);
	printf("%f",a[0][3]);
	return 0;	
}

void readdata1()
{
	freopen("p_test.txt","rb",stdin);
    int len = fread(buf,1,MAXS,stdin);
    buf[len] = '\0';
	char *p;
	const char *split=" ";
	p=strtok(buf,split);
	int i=0,j=0;
	while(p!=NULL)
	{
		*(*(a+i)+j)=myatof(p);
		j++;
		if (j==71028)
		{
			j=0;
			i++;
		}
		p=strtok(NULL,split);
	}
}
当然,读取的文件都是char*型的,还必须转换为float型,而系统"stdlib.h"的atof函数正好可以使用。但是考虑到数据文件的范围为-100到100,

故参考网上“自己实现的atof()和atoi()代码”一文,改了一个myatof的函数,如下,

double myatof(const char* sptr)
{
    double temp=10;
    bool ispnum=true;
    double ans=0;
    if(*sptr=='-')//判断是否是负数
    {
        ispnum=false;
        sptr++;
    }
    else if(*sptr=='+')//判断是否为正数
    {
        sptr++;
    }
    while(*sptr!='\0')//寻找小数点之前的数
    {
        if(*sptr=='.'){ sptr++;break;}
        ans=ans*10+(*sptr-'0');
        sptr++;
    }
    while(*sptr!='\0')//寻找小数点之后的数
    {
        if (*sptr=='e' || *sptr=='E'){sptr+=3;break;}
		ans=ans+(*sptr-'0')/temp;
        temp*=10;
        sptr++;
    }
	int cifang=*sptr-'0';
	float sumcifang=1;
	while(cifang--){sumcifang*=10;}
    if(ispnum) return ans*sumcifang;
    else return ans*(-1)*sumcifang;
}

这样,读取整个文件花费的时间为2.9s,远小于其他方法所需时间。(release版本为1.4s)


版权声明:本文为wzy1990原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。