2016-12-06 6 views
1

Я читаю из файла excel. В одном из столбцов (который включает только очень длинные номера) MATLAB импортировал его как CELL (потому что есть заголовок).Преобразование MATLAB: CELL to DOUBLE; Но цифры меняются

Это образец импортирован:
'980000684210053338'

Это мои попытки:

Преобразует в DOUBLE, но цифры меняются
tableM.v1 = cellfun(@str2num,tableM.v1);

Преобразование в DOUBLE, но цифры меняются
tableM.v1 = cellfun(@str2double,tableM.v1);

Преобразование в CHAR, но номера являются правильными
tableM.v1 = cell2mat(tableM.v1);

Как преобразовать этот CELL, чтобы удвоить, сохраняя при этом правильные значения?

P.S. Я использую MATLAB R2016a.

UPDATE:
Я побежал этот код из ответов:
tableM.v1 = vpa(tableM.v1); % assuming tableM.v1 is a cellstr

И я получил эту ошибку:

Warning: Support of strings that are not valid variable names or define a number will be removed in a future release. To create symbolic expressions, first create symbolic variables and then use operations on them.
In sym>convertExpression (line 1536)
In sym>convertChar (line 1441)
In sym>tomupad (line 1198)
In sym (line 177)
In cell2sym (line 28)
In sym>tomupad (line 1208)
In sym (line 177)
In vpa (line 44)
Error using symengine
New array must have the same number of elements as the original array.

Error in sym/reshape (line 50)
ySym = mupadmex('symobj::reshape',x.s,args{:});

Error in cell2sym (line 34)
S = reshape(sym([Csym{:}]), size(C));

Error in sym>tomupad (line 1208)
xsym = cell2sym(x);

Error in sym (line 177)
S.s = tomupad(x);

Error in vpa (line 44)
ss = sym(s);

ответ

1

Лучше Ответ

Ответ вниз ниже принятый ответ, но в то время как проволочки на что-то, я понял, что это слишком умный.Я думаю, что вы действительно хочет использовать textscan:

tableM.v1 = cellfun(@(x) textscan(x, '%u64'), tableM.v1); 

TextScan уже есть чеки экспонента и десятичные, идет прямо к целому классу, не проходя через двойной, и получаете переполнения правого (мой пример переполнения ниже ISN» t совершенно верно, потому что вектор экспоненты также переполняется. Максимум uint64 на самом деле 9223372036854775807). Вместо хорошего вектора, однако, вы получите массив ячеек, потому что это то, что выкидывает textscan. Любое плохо сформированное число приведет к пустым ячейкам, с которыми вам придется иметь дело до преобразования в вектор.

>> in = {'cat', '1e10', '980000684210053338}; 
>> out = cellfun(@(x) textscan(x, '%u64'), in) 
out = 

    1×3 cell array 

    [0×1 uint64] [10000000000] [980000684210053338] 

После того, как вы исправили те, вы можете преобразовать в вектор с cell2mat.


Оригинал ответа

Как и другие ответы указывают, двойники просто не может держать эти цифры из-за потери точности. Вам нужно передать их в 64-битное целое число без предварительного прохождения через фильтр double. Попробуйте эту функцию три строки:

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 есть флаг, чтобы сказать, что он будет суммироваться без кастинга. Я не знаю, когда был выпущен этот флаг, поэтому ваш пробег может отличаться. Если у вас нет этой опции, вам придется делать сумму в цикле вместо этого.

Еще одна оговорка: эта функция не имеет проверки ввода или вывода, поэтому (Я просто конвертирую числа на основе их положения в таблице ASCII) и str2uint64('1000000000000000000') = 18446744073709551615 (переполнение). Используйте на свой риск.


+0

Nice +1. Я был очень удивлен, увидев, что у MATLAB еще нет набора 'str2int * '. Внутреннее «двойное» литье также действительно странно и раздражает. Я заметил это, по какой-то причине, происходит при преобразовании нескаляра VPA в 'uint64':' str = '980000684210053338'; disp (uint64 (vpa (str))); disp (uint64 (vpa (repmat ({str}, 1,2)))); 'производит разные результаты, что смешно. – TroyHaskin

+0

Это, похоже, работает, хотя одна небольшая проблема. Он преобразует «0,0090» в «90» или «3,5610» в «305610». – PeyM87

+0

Ваш пример не включает символы, отличные от цифр. Вот почему я добавил последнее предупреждение об ошибке. Функция также предполагает, что ваши входы уже целые, а не плавающие, потому что вы не указали, что это вариант. Для поиска десятичного индикатора потребуется несколько дополнительных шагов, а затем усечь число. – craigim

1

двойной точности номера имеют по-большей 15 stable decimal places или, как MathWorks puts it , "double значения не могут представлять все целые числа, превышающие 2 правильно". Поскольку число Excel составляет 18 значащих десятичных знаков в длину, потеря точности до double конверсия неизбежна.

Чтобы избежать потерь точности, вы можете преобразовать строки в число, которые используют variable precision arithmetic:

tableM.v1 = vpa(tableM.v1); % assuming tableM.v1 is a cellstr 

Это более чем вероятно производительность убить, но это отдающий для точного представления (пока MATLAB изначально не поддерживает 128-битная точка с плавающей запятой, которая, вероятно, далека во времени и, в любом случае, более интенсивна).

В теории, uint64 может также провести целое число точно, но есть не кажется, чистый способ, чтобы преобразовать строку в п битовое целое число, которое я могу найти.

+0

При получении этого кода я получаю ошибки. Я обновил вопрос с ошибкой. – PeyM87

+0

@ PeyM87 Это говорит мне, что 'tableM.v1' не является полностью массивом ячеек строк, содержащих только числа. Это единственный способ, которым это будет работать. – TroyHaskin

 Смежные вопросы

  • Нет связанных вопросов^_^