How to reformat the display output precision of e.g. the TF() function?

5 views (last 30 days)
When asking for a transfer function, given a state-space object sysd, MATLAB prints the result like this:
>> tfd = tf(sysd)
tfd =
0.05563 z + 0.05568
----------------------
z^2 - 1.988 z + 0.9923
The precision used is insufficient for my purposes (I need more than 7 significant digits). It appears not to be possible to use e.g. "format long e" to change this?
Of course I can ask for tfd.num and tf.den and print these arrays with long e, but that is not very convenient (I like the pretty printed display and don't see an easy way to write that myself). How to instruct MATLAB to use the proper format in this case?
PS: There are more functions and figures that display data in difficult to change numeric formats or in ugly windows (like the Bode and pz diagrams from the control toolbox). It would be nice if one could change all that in a (semi-)permanent way.
  4 Comments
marcel hendrix
marcel hendrix on 7 May 2022
@Paul: > Or, in other words, why is seeing those extra few digits important?
Good question. My current way of working is that I copy the output of commands like this with the mouse and directly paste them into the application (here a SPICE netlist of a digital controller circuit). The formatted text then also serves as documentation where these numbers are coming from. This specific display does not only tell the value of the coefficients, but also if they belong in the numerator or denominator and to what power of 'z' they apply.
A few more digits may seem unimportant, however, for transfer functions only 5 significant digits for the polynomial coefficients can mean more than 1 Volt of DC offset in a steady state solution.

Sign in to comment.

Accepted Answer

Paul
Paul on 7 May 2022
The function poly2str in the CST may be of interest, I think that the numerical formatting is governed by a single line, so I guess you could make a local copy and modify that line and go from there.
which poly2str
/MATLAB/toolbox/control/ctrlobsolete/poly2str.m
Here's my attempt. I have not fully tested it and so there may be (probably are!) some corner cases I haven't considered.
User beware.
It assumes a discrete time tf in the variable z. I'm sure it could be generalized.
rng(100);
tfd = tf(rand(1,3).*[-1 -1 1],rand(1,5).*[1 -1 1 -1 1],-1)
tfd = -0.5434 z^2 - 0.2784 z + 0.4245 ---------------------------------------------------------- 0.8448 z^4 - 0.004719 z^3 + 0.1216 z^2 - 0.6707 z + 0.8259 Sample time: unspecified Discrete-time transfer function.
localdisptf(tfd);
tfd = -0.5434049417909654 z^2 - 0.2783693850937962 z + 0.4245175907491331 ---------------------------------------------------------------------------------------------------------------------- 0.8447761323199037 z^4 - 0.004718856190972565 z^3 + 0.1215691207831142 z^2 - 0.6707490847267786 z + 0.8258527551050476
tfd = tf([-1 1],[1 -2.00000001 1],-1)
tfd = -z + 1 ------------- z^2 - 2 z + 1 Sample time: unspecified Discrete-time transfer function.
localdisptf(tfd);
tfd = -z + 1 ---------------------- z^2 - 2.00000001 z + 1
tfd = tf([-1],[-1 -1 1],-1)
tfd = 1 ----------- z^2 + z - 1 Sample time: unspecified Discrete-time transfer function.
localdisptf(tfd);
tfd = -1 ------------ -z^2 - z + 1
Matlab always displays with leading coeffficient of denominator positive. Code can be modfied if desired.
tfd = tf(1.000004,-5.31256,-1)
tfd = -0.1882 Static gain.
localdisptf(tfd);
tfd = 1.000004 -------- -5.31256
Matlab displays static gains as a single number. Code can be modified if desired.
function polystr = localpolystr(polynomial)
polystr = split(string(num2str(polynomial,16))); % change fmt as needed, or it can be a function input
firstnonzero = find(polystr~= "0",1);
polystr(1:firstnonzero-1) = [];
for ii = 1:numel(polystr)-1
polystr(ii) = polystr(ii) + " z^" + string(numel(polystr)-ii);
end
polystr = erase(polystr,"^1");
negativeterms = find(extractBefore(polystr,2) == "-");
negativeterms(negativeterms == 1) = []; % leading coefficent
polystr(negativeterms) = extractAfter(polystr(negativeterms),1);
dividers = ["" ; repmat(" + ",numel(polystr)-1,1)];
dividers(negativeterms) = " - ";
unityterms = find(extractBefore(polystr(1:end-1),3) == "1 ");
polystr(unityterms) = extractAfter(polystr(unityterms),2);
% special case for -1 leading coefficient of a polynomial
if numel(polystr) > 1 && extractBefore(polystr(1),3) == "-1"
polystr(1) = "-" + extractAfter(polystr(1),3);
end
polystr = dividers + polystr;
polystr = join(polystr,"");
end
function localdisptf(htf)
num = htf.num{1};
den = htf.den{1};
denstr = localpolystr(den);
numstr = localpolystr(num);
divider = join(repmat("-",1,max(strlength(denstr),strlength(numstr))),"");
tfstrings = strjust(pad([numstr;divider;denstr]),'center');
disp(inputname(1) + " =")
disp(tfstrings(1));
disp(tfstrings(2));
disp(tfstrings(3));
end
  2 Comments
Paul
Paul on 7 May 2022
Happy to help. Please post back if you discover any problems.
If you need to have the exact representation in your other application as in Matlab, please investigate how to use the precision or format input to num2str() to make sure the string representation of a number (assumed to be a double) is the number. I thought that 16 digits of precision is correct for doubles, but I'm far from an expert on internal floating point representation.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

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

Start Hunting!