Is there an easy way to format numbers to 3 significant figures?
929 views (last 30 days)
Show older comments
Is there an easy way to format numbers into scientific notation with 3 significant figures?
Such as:
4.53
or
1.03e+09
1 Comment
D Huntsman
on 25 Sep 2018
round(var,digit,'significant')
where var is the variable of interest and digit is number of significant digits.
Answers (5)
Jan
on 28 Apr 2021
If "3 significant figures" mean before and after the decimal point:
fprintf('%.3g', pi)
fprintf('%.3g', pi * 1e9)
4 Comments
Walter Roberson
on 2 Feb 2023
.$ matches any character at the end of the string. To match dot specifically use \.$
Steven Lord
on 30 Jan 2018
Use the round function with two input arguments. If this does not work, tell us which release of MATLAB you're using.
round(pi, 2)
0 Comments
Star Strider
on 30 Jan 2018
A = 6.022140857E+23;
N = sprintf('Avogadro''s number = %9.2E', A)
N =
'Avogadro's number = 6.02E+23'
2 Comments
Star Strider
on 30 Jan 2018
Edited: Star Strider
on 28 Apr 2021
‘Does this mean I have to display as a string and not a number?’
To display it, yes.
MATLAB retains full internal precision, so you lose nothing. The format (link) function is the only way you can control the Command Window and tooltip format.
‘I currently have my values in a matrix and convert it into a table.’
If by ‘table’ you intend the table (link) data type, those appear to have their own internal (and unchangable) format. Formatting options are not listed among the ‘Properties’ in a table, although there may be an undocumented way to change it.
—————
EDIT — (28 Apr 2021 at 20:20)
For the last few MATLAB versions, the round function has had a number of new options added to it, one of which is Round Elements to Specified Number of Significant Digits. It is likely worth upgrading to get these and other enhancements to various functions.
.
John Olesik
on 8 Jan 2019
Strickly speaking neither command gives the proper number of significant digits. The correct result for pi in 2 significant digits would be 3.1 with no 0s to the right of the 1. round(pi,2,'significant') gives 3.1000 which as written has 5 significant digits. If you ignore the 0s then it has the correct number of significant digits. round(pi,2) gives 3.1400 which again has 5 significant digits as written (even though the 0s are not correct). round(pi,2) specifies using two non-zero digits to the right of the decimal point, not two significant digits.
1 Comment
Stephen23
on 8 Jan 2019
Edited: Stephen23
on 8 Jan 2019
"round(pi,2,'significant') gives 3.1000 which as written has 5 significant digits"
Strickly speaking you are confusing two related but very different things: the precision of the numeric class (which is fixed and cannot be changed) with how numeric values are displayed (which for binary floating point number is often an approximation of the real binary value, as in all of your example values). Floating point numbers are introduced here (and in thousands of tutorials on the internet):
Those five decimal digits (those nice trailing zeros) are simply caused by the current format setting, and are totally independent of any rounding or anything else you might have done to your values beforehand.
Your claim that "the 0s are not correct" is not correct: for the values 3.1 and 3.14 that you show cannot be stored exactly as binary floating point numbers, so the values that you see displayed are approximations of the values that are actually stored in memory: the trailing zeros correctly represent that binary floating point value as a decimal to the precision shown by the zeros:
>> N = round(100*pi)/100
N = 3.1400
>> fprintf('%.40f\n',N)
3.1400000000000001243449787580175325274467
If you want to see the real values stored by the binary floating point class then download James Tursa's excellent num2strExact.
Real User
on 28 Apr 2021
Edited: Real User
on 29 Apr 2021
[Fixed] Use this function to format a number to sig significant digits (if you want fixed format, not exponential, and not loose any accuracy of the integer part, or you want to set the maxlength, or the like). For example,
>> fprintf('%s', str_significant(12.34567, 4))
12.35>> fprintf('%s', str_significant(12387654321.987, 3))
12387654322>> fprintf('%s', str_significant(-0.01289, 3, 0, 6)) % 6 = maxlength of the string
-0.013>> fprintf('%s', str_significant(0.01289, 3, 0, 6))
0.0129>>
See further examples below, including the comparison to %.3f and %.3g.
Note: IF YOU WANT TO ROUND ALSO THE INTEGER PART (when it happens to have too many significant digits), uncomment the line above "Uncomment the above line ..." at the end of the comment section.
function str = str_significant(value, sig, minlength, maxlength)
% str = "sprintf(value)" except for minlength and adjusting the number of decimals.
% if round(value) has at least sig digits, use it.
% else: round to so many decimals that you have sig significant digits
% (OR LESS if maxlength requires). (maxlength is used only for this purpose)
% Always: length(str) >= minlength. (Adds leading spaces if necessary.)
% Uses "fixed format", never "exponential format".
%
% N.B. What you see is correctly rounded, if rounding is used
% (but only decimals are rounded away, as many as necessary).
% maxlength is violated iff the integer part is longer than maxlength.
% Matlab may add rounding errors, e.g., after 17 correct digits, so you only see them if you require too many digits.
%
% EXAMPLES: str_significant(12387654321.987, 3) = '12387654322'.
% str_significant(0.00001238, 3) = '0.0000124'.
% str_significant(0.12387654321, 3) = '0.124'. sprintf('%.3g', 12.387654321) = '12.4'.
% str_significant(-0.01289, 3, 8, 6) = ' -0.013'. % 6 = maxlength of the string, 8 = minlength
% str_significant(0.01289, 3, 0, 6) = '0.0129'. str_significant(-35.2987, 7, 0, 6)) = '-35.30'.
% sprintf('%.3f', 0.00001238) = '0.000'. sprintf('%.3g', 1.238) = '1.24'.
% sprintf('%.3g', 1.238e9) = '1.24e+09'. sprintf('%.3g', 1238345.49) = '1.24e+06'.
% sprintf('%.3g', 0.0001238) = '0.000124'. sprintf('%.3g', 0.00001238) = '1.24e-05'.
%
% % value = round(value, sig, 'significant');
% % Uncomment the above line IF YOU WANT TO ROUND ALSO THE INTEGER PART, when it is too accurate.
if (nargin < 4)
maxlength = 999;
if (nargin < 3)
minlength = 0;
end
end
if (value==0)
str = '0';
return;
end
lenint = length(sprintf('%d', round(abs(value)))); % length of the integer part
lenintm = lenint + (value<0); % -"- plus 1 if minus sign
maxdec = max(maxlength-lenintm-1, 0); % lenint+point+decimals <= maxlength required.
if (value >= 1 || value <= -1)
decimals = max(min(sig-lenint, maxdec), 0); % sig-lenint decimals needed.
else
Nzeros = ceil(-log10(abs(value))) - 1; % # zeros after the decimal point before the first number
decimals = min(maxdec, sig + Nzeros);
end
str = sprintf('%*.*f', minlength, decimals, value);
3 Comments
Jan
on 29 Apr 2021
The usual definition of the term "significant digits" include the digits before the decimal point also.
Real User
on 29 Apr 2021
Edited: Real User
on 30 Apr 2021
Yes. If you always want at most sig significant digits (even if it does not save any space), uncomment the line above "Uncomment the above line...". (I now repeated this in capitals in the leading text to avoid people missing this.)
Without uncommenting, the above code rounds down to sig digits only as far as it shortens the output. So you minimize the output by rounding but require at least sig significant digits (unless maxlength forces you to go below that). This is how I needed it to have (to maximize the info but minimize the space), but somebody else might uncomment that line to make the information clearer (but less accurate) even if it does not save any space.
See Also
Categories
Find more on Characters and Strings in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!