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位整数,而不先通过doublefilter。 试试这个三行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位整数。