最近在跟着导师做项目的过程中,需要处理大批的数据,数据存储的方式和形式有很多种,我选择了存储在excel表中,因为这样可以比较直观地看出每一行、每一列的数据特点。matlab写入和读取excel表可以采用xlswrite( )函数和xlsread( )函数简单进行。
示例:
matlab写入excel表:
xlswrite('test.xlsx',datasets,1,'A1:Z256');
matlab读取excel表:
testing_data = xlsread('test.xlsx',1,'A1:Z257');
我在写入数据时遇到了一个问题:调用xlswrite()函数时需要注明从哪个位置写到哪个位置,这两个位置信息分别包含行列信息。
我们根据前面的代码能够很清楚地知道需要从第几列写到第几列,但是excel表的列是按照字母来标注的,这里涉及一个任意数字到字母的转换问题。
也就是我知道1对应第A列,26对应第Z列,那么诸如567、1024这些数字呢?
初步探索:
刚开始我认为这只不过是26进制的一种表示方法,所以参考网上给出的一些代码,编写了涉及进制转换的代码,如下:
num = 25;
k = floor(log(num)/log(26)); % 检验输入数据中最高包含26的几次方
col = [];
j = 0;
for i = k:-1:0
j = j+1;
mn = 26^i;
temp = floor(num/mn); % 依次为26次方前的系数
col(j) = temp;
num = num - mn*temp;
end
[m,n] = size(col);
col_letter = [];
for i = 1:1:n
letter = char('A'+col(i)-1); % 计算相应位置上的字母
col_letter = strcat(col_letter,letter); % 字符连接
end
col_letter
疑点发现:
这个代码在一些情况下会出现其他不属于字母A~Z的特殊字符。
我思考了一下原因,但后来发现:字母中的A代表的是第1位,而缺乏第0位这个元素,所以跟普通的26进制还是有些不同的。
也就是说普通10进制中每一位包含的数字范围是:0、1、2、3、4、5、6、7、8、9,而不会出现某一位为10的情况;
普通8进制中每一位包含的数字范围是:0、1、2、3、4、5、6、7,也不会出现某一位为8的情况;
而字母表示的26进制中,每一位包含的字母范围都分别是A~Z这26个字母,他们对应的数字分别是1~26,而不会出现某个字母对应数字为0。
针对这种细微的差别,我们来思考上述代码在什么情况下,会出现错误呢?
首先,我们来看普通十进制数的转换:
![](https://img-blog.csdnimg.cn/20200917222817306.png)
![](https://img-blog.csdnimg.cn/20200917222817356.png)
然而,我们现在面对的进制转换问题中,对于不出现Z的字母:
![](https://img-blog.csdnimg.cn/20200917222817310.png)
转换结果正常;
当出现Z时:
![](https://img-blog.csdnimg.cn/20200917222817262.png)
![](https://img-blog.csdnimg.cn/20200917222817346.png)
即:当我们输入数字
![](https://img-blog.csdnimg.cn/20200917224248643.png)
由上述代码经过转换就会出现‘ABD@’这个结果。
![](https://img-blog.csdnimg.cn/20200917222817335.png)
![](https://img-blog.csdnimg.cn/20200917222817278.png)
又即:当我们输入数字
![](https://img-blog.csdnimg.cn/20200917224440526.png)
由上述代码经转换会出现‘AC@@’这个结果。
也就是含有字母'Z'的字符串在转换过程中会出错。
疑点修正:
因为我们知道,当Z字母出现在字符串的某一位时,由于特殊的进位关系,会导致对应数组的该位出现0元素。
我们的最终转换规则为1~26分别对应A~Z,由于没有指定0元素的转换关系,因而会出现特殊字符。
综合上述的现象,我可以先计算输入的任意数字分别包含26的多少个次幂,并存入一个数组,从高到低(从后往前)依次检验这个数组各位是否存在0元素;
若存在,则该位加26(对应字母为Z),而将前一位减1;
进一步,若前一位减1后为0,则继续上述循环操作;同时,若减1后出现某一位为-1,则说明该位及其后一位为连续字符串‘YZ’,同样将该位加26,并将前一位减1,继续上述循环操作,直到遍历整个数组。
注意,不考虑循环过程中数组第一位为0或-1的情况。
其后,调整数组长度:当首位元素为0时,将其去除。
最后,将数组各位转换成相应字母,转换规则为1~26分别对应A~Z,转换好后用strcat()函数进行字符串连接。完毕。
数字转换字母的完整函数如下:
function [col_letter] = num2xls_letter(num)
% note:Convert Numbers to letters
% num =1*26^3+2*26^2+4*26+0*26^0;
% num = 25;
k = floor(log(num)/log(26));
col = [];
j = 0;
for i = k:-1:0
j = j+1;
mn = 26^i;
temp = floor(num/mn);
col(j) = temp;
num = num - mn*temp;
end
[m,n] = size(col);
for i = n:-1:1
if ((col(i) == 0)||(col(i) == -1))&&(i~=1) % 检查相应位是否为0或-1,且不对最高位检查
col(i) = col(i) + 26; % 调整当前位
col(i-1) = col(i-1)-1; % 调整前一位
end
end
if col(1) == 0
col = col(2:end);
end
[m,n] = size(col);
col_letter = [];
for i = 1:1:n
letter = char('A'+col(i)-1);
col_letter = strcat(col_letter,letter);
end
col_letter
end
另附字母转换数字的函数如下:
function [number] = xls_letter2num(str)
% note:Convert letters to Numbers
% str = 'ZBED';
num = str + 0;
num1 = num - 64;
[m,n] = size(num1);
number = 0;
for i = 1:1:n
number = number + num1(i)*26^(n-i);
end
end