num2str weird behavior with decimal input....

6 views (last 30 days)
Gabriel
Gabriel on 10 Mar 2015
Commented: Stephen23 on 11 Mar 2015
I am trying to get matlab to output a string of length 2 for any number between 0 and 99. In that particular case, my input is between 0 and 0.99. So I tryed num2str(X*100,'%0.2u') where X is my input. Now, here is what happens:
X = 0.03 => num2str(X*100,'%0.2u'): ans = '03'
X = 0.05 => num2str(X*100,'%0.2u'): ans = '05'
X = 0.08 => num2str(X*100,'%0.2u'): ans = '08'
X = 0.1 => num2str(X*100,'%0.2u'): ans = '10'
but
X = 0.07 => num2str(X*100,'%0.2u'): ans ='7.00e+00'
I am working with Matlab 2014b and have exactly that problem on two different computers. Does someone understand why and what can be done?
Thank you very much!
  3 Comments
Jan
Jan on 10 Mar 2015
Conclusion of the given answers: This behavior is not weird, but expected and wanted. You've expected something else, but here only these expectations are not suiting.
Stephen23
Stephen23 on 11 Mar 2015
@Gabriel: rather than convert the number class, just use a more suitable format, as I explained in my answer.

Sign in to comment.

Answers (3)

Stephen23
Stephen23 on 10 Mar 2015
Edited: Stephen23 on 10 Mar 2015
As explained by Michael Haderlein, this is caused by non-integer values resulting in the default '%e' format being used. For better control without requiring that the variables are first converted to an integer class or rounded (slow!), consider simply using the format '%02.0f' instead:
>> X = [0.03; 0.05; 0.08; 0.07];
>> fprintf('%02.0f\n',100*X)
03
05
08
07
Note that I used fprintf , both sprintf and num2str use the same format strings as well, but num2str is the slowest.

Michael Haderlein
Michael Haderlein on 10 Mar 2015
Edited: Michael Haderlein on 10 Mar 2015
You already pointed to the correct reason with your comment. It's basically about floating point arithmeticts.
>> [0.03*100-3;
0.05*100-5;
0.08*100-8;
0.07*100-7]
ans =
1.0e-15 *
0
0
0
0.8882
You see that for the computer 0.07*100 is not 7 (obviously the binary representation of 0.07 is rather poor - but there are similar cases for other floating point numbers).
In the Matlab help (I checked the sprintf documentation, but it will be in other functions, too) it is written:
If you specify a conversion that does not fit the data, such as a string conversion for a numeric value, MATLAB® overrides the specified conversion, and uses %e.
That's exactly what happens here. Your fix is fine therefore, because it's exactly addressing this issue. You might think about using uint16/uint32 as converted data type because that's what you use in your string format, but that's not too important, I think.

James Tursa
James Tursa on 10 Mar 2015
FYI, here are the exact decimal conversions of the IEEE double floating point bit patterns in question:
>> num2strexact([.01,.02,.03,.04,.05,.06,.07,.08,.09,.10]')
ans =
'1.000000000000000020816681711721685132943093776702880859375e-2'
'2.00000000000000004163336342344337026588618755340576171875e-2'
'2.99999999999999988897769753748434595763683319091796875e-2'
'4.0000000000000000832667268468867405317723751068115234375e-2'
'5.000000000000000277555756156289135105907917022705078125e-2'
'5.9999999999999997779553950749686919152736663818359375e-2'
'7.0000000000000006661338147750939242541790008544921875e-2'
'8.000000000000000166533453693773481063544750213623046875e-2'
'8.99999999999999966693309261245303787291049957275390625e-2'
'0.1000000000000000055511151231257827021181583404541015625'
>> num2strexact([.01,.02,.03,.04,.05,.06,.07,.08,.09,.10]'*100)
ans =
'1'
'2'
'3'
'4'
'5'
'6'
'7.00000000000000088817841970012523233890533447265625'
'8'
'9'
'1e1'
You can find num2strexact here:

Categories

Find more on Matrices and Arrays in Help Center and File Exchange

Tags

Products

Community Treasure Hunt

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

Start Hunting!