Azzera filtri
Azzera filtri

Str2num: exact the same conversion

6 visualizzazioni (ultimi 30 giorni)
Xiaohan Du
Xiaohan Du il 3 Mar 2018
Commentato: Stephen23 il 4 Mar 2018
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 Commenti
Rik
Rik il 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.
Stephen23
Stephen23 il 4 Mar 2018
"How can I get exactly 0.0000000001?"
It is not possible to store 0.0000000001 exactly using binary floating point numbers.

Accedi per commentare.

Risposta accettata

Walter Roberson
Walter Roberson il 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.

Più risposte (0)

Categorie

Scopri di più su MATLAB in Help Center e File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by