MATLAB Answers

Str2num: exact the same conversion

조회 수: 27(최근 30일)
Hi all,
Quick question: I have a string like this:
rawStrMod = '0.0000000001, 0.3'
I use str2num to convert it to number,
>> str2num(rawStrMod)
ans =
0.000000000100000 0.300000000000000
It gives me 0.000000000100000, not exactly the same as 0.0000000001. Here I use format long. If I change to format short g, it gives me:
>> format short g
>> str2num(rawStrMod)
ans =
1e-10 0.3
How can I get exactly 0.0000000001?

  댓글 수: 2

Rik
Rik 3 Mar 2018
Is it just that you want the values to be shown in a specific format? Because the result in both cases is the exact same value, Matlab just shows them differently in the two cases.
Stephen Cobeldick
Stephen Cobeldick 4 Mar 2018
"How can I get exactly 0.0000000001?"
It is not possible to store 0.0000000001 exactly using binary floating point numbers.

로그인 to comment.

채택된 답변

Walter Roberson
Walter Roberson 3 Mar 2018
rawStrMod = '0.0000000001, 0.3';
"It gives me 0.000000000100000, not exactly the same as 0.0000000001."
Ignoring formatting issues, none of the Mathworks toolboxes are able to give you exactly the same as 0.0000000001 . MATLAB is not able to store 0.0000000001 exactly in binary floating point: the closest it can get in binary floating point is 0.00000000010000000000000000364321973154977415791655470655996396089904010295867919921875
The closest Mathworks tool can get is by using the Symbolic Toolbox, for which sym('0.0000000001') gives you something that is closer to 0.0000000001 than you can get without the Symbolic Toolbox, but if you probe hard enough you can prove that sym('0.0000000001') is implemented as a binary ratio whose asymptotic accuracy is bounded by truncations of 10/3 bits per digit of accuracy requested (log2(10) would perhaps be expected but the model turned out to be 10/3: some of the bits are being used for overhead of extended precision values.)
Everything else is just formatting (and perhaps keeping track of sizes). There are only a few formatting options available for default numeric display. For anything else you should be using sprintf() or fprintf() for fine detailed display.
rawStrMod = '0.0000000001, 0.3, 0.0000000001000, 123';
T = regexp(rawStrMod, '\s*,\s*', 'split');
T_numeric = str2double(T);
T_input_digits = cellfun(@length,regexprep(T,{'^[^.]*$', '^.*\.'},{'', ''},'once', 'lineanchors'));
T_data = num2cell( [T_input_digits(:),T_numeric(:)].' );
fprintf('%.*f\n', T_data{:});
Output is
0.0000000001
0.3
0.0000000001000
123
The input was converted to numeric (T_numeric), but the number of decimal places was tracked, and that number is used to format the output.
This code does have a subtle problem:
  • if you have an integer like the 123, then it is entirely reasonable that the output should not contain a decimal place, like happens here, with the number of decimal places being detected to be 0
  • however, if the 123 were instead 123. with no digits following the decimal places, then the number of decimal places would be considered to be 0, and when told to use 0 decimal places, the %f format item does not put in the trailing decimal point, so 123. would print out as 123 with the code as implemented being unable to format 123 on input differently than 123. on input.

  댓글 수: 0

로그인 to comment.

More Answers (0)

이 질문에 답변하려면 로그인을(를) 수행하십시오.


Translated by