MATLAB转换:CELL到DOUBLE; 但数字改变
我正在阅读一个excel文件。 在其中一列(只包含很长的数字)中,MATLAB将其导入为CELL(因为有一个标题)。
这是导入的示例:
'980000684210053338'
这些是我的尝试:
转换为DOUBLE,但数字更改
tableM.v1 = cellfun(@str2num,tableM.v1);
转换为DOUBLE,但数字更改
tableM.v1 = cellfun(@str2double,tableM.v1);
转换为CHAR,但数字是正确的
tableM.v1 = cell2mat(tableM.v1);
如何将这个CELL转换为DOUBLE,同时保持正确的值?
谢谢
PS我正在使用MATLAB R2016a。
更新:
我从答案中运行这个代码:
tableM.v1 = vpa(tableM.v1); % assuming tableM.v1 is a cellstr
而我收到这个错误:
警告:支持非有效variables名称的string或定义号码将在未来版本中删除。 要创build符号expression式,首先创build符号variables,然后使用它们的操作。
在sym> convertExpression(1536行)
在sym> convertChar(1441行)
在sym> tomupad(1198行)
在sym(第177行)
在cell2sym(第28行)
在sym> tomupad(1208行)
在sym(第177行)
在vpa(第44行)
错误使用symengine
新数组必须具有与原始数组相同数量的元素。sym /重塑(第50行)
ySym = mupadmex('symobj :: reshape',xs,args {:});在cell2sym(第34行)
S = reshape(sym([Csym {:}]),size(C));在sym> tomupad(1208行)
xsym = cell2sym(x);sym中的错误(第177行)
Ss = tomupad(x);错误在vpa(第44行)
ss = sym(s);
更好的答案
下面的答案是可以接受的答案,但在拖延某些事情的时候,我意识到这太聪明了。 我认为你真正想要的是使用textscan
:
tableM.v1 = cellfun(@(x) textscan(x, '%u64'), tableM.v1);
Textscan已经具有指数和小数的检查,直接到整数类而不通过双重,并获得溢出权(下面的溢出示例是不完全正确的,因为指数vector也溢出,最大uint64
实际上是9223372036854775807)。 然而,如果不是一个漂亮的vector,你将会得到一个单元格数组,因为这就是textscan
结果。 任何forms不好的数字都会导致空单元格,在转换为vector之前,您将不得不处理这些空单元格。
>> in = {'cat', '1e10', '980000684210053338}; >> out = cellfun(@(x) textscan(x, '%u64'), in) out = 1×3 cell array [0×1 uint64] [10000000000] [980000684210053338]
一旦你解决了这些问题,你可以用cell2mat
转换成vector。
原始答复
正如其他答案所指出的那样,由于精确度的损失,双打不能保持这些数字。 您需要将它们转换为64位整数,而不先通过double
filter。 试试这个三行function:
function out = str2uint64(in) % Convert the digits into an array of numbers and cast to % uint64 in = uint64(in - 48); % Create the order of magnitude for each digit and convert % that also to uint64 exponents = uint64(logspace(numel(in)-1, 0, numel(in))); % Why would sum default to convert your numbers to doubles?!? % The 'native' tag is recent, I believe, but if you have it, % it will preserve the data type. out = sum(in .* exponents, 'native'); end
使用:
tableM.v1 = cellfun(@str2uint64,tableM.v1);
一个警告是,由于一些愚蠢的原因,当MATLAB总结数字,它把它们double
。 在当前版本R2016b中,有一个标志可以告诉它总结而不投射。 我不知道那个国旗何时发布,所以你的里程可能会有所不同。 如果你没有这个选项,你将不得不在循环中进行总和。
另一个警告:这个函数没有input或输出检查,所以str2uint64('cat') = 5658
(我只是根据它们在ASCII表中的位置转换数字)和str2uint64('1000000000000000000') = 18446744073709551615
(溢出)。 使用风险自负。
双精度数最多有15个小数位,或者像MathWorks所说的那样 ,“ double
精度数不能正确表示所有大于2 53的整数”。 由于Excel的数字是十八位有效的小数位,因此double
转换的精度损失是不可避免的。
为了避免精度损失,可以将string转换为使用可变精度算术的数字:
tableM.v1 = vpa(tableM.v1); % assuming tableM.v1 is a cellstr
这样做很可能会导致性能下降,但这是确切代表性的回报(直到MATLAB本身支持128位浮点,这两者都有可能在很短的时间内完成,而且无论如何都会影响性能)。
从理论上讲, uint64
也可以保持整数,但似乎没有一个干净的方式来将string转换为我可以find的n位整数。