Clear Filters
Clear Filters

Is there an easy way to format numbers to 3 significant figures?

636 views (last 30 days)
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
D Huntsman on 25 Sep 2018
round(var,digit,'significant')
where var is the variable of interest and digit is number of significant digits.

Sign in to comment.

Answers (5)

Jan
Jan on 28 Apr 2021
If "3 significant figures" mean before and after the decimal point:
fprintf('%.3g', pi)
3.14
fprintf('%.3g', pi * 1e9)
3.14e+09
  3 Comments
PetterE
PetterE on 2 Feb 2023
The annoying edge case can be fixed with a regex replacement.
regexprep(sprintf('%#.3g',100),'.$','')
ans = '100'
The regex ( '.$' ) matches a dot at the end of the string and replaces it with nothing.
Walter Roberson
Walter Roberson on 2 Feb 2023
.$ matches any character at the end of the string. To match dot specifically use \.$

Sign in to comment.


Steven Lord
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)

Star Strider
Star Strider on 30 Jan 2018
See the documentation on the sprintf (link) function.
A = 6.022140857E+23;
N = sprintf('Avogadro''s number = %9.2E', A)
N =
'Avogadro's number = 6.02E+23'
  2 Comments
Campbell Gray
Campbell Gray on 30 Jan 2018
Does this mean I have to display as a string and not a number?
I currently have my values in a matrix and convert it into a table.
Star Strider
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.
.

Sign in to comment.


John Olesik
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
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.

Sign in to comment.


Real User
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
Jan on 29 Apr 2021
The usual definition of the term "significant digits" include the digits before the decimal point also.
Real User
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.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!