Matlab Producing Different Values Running Entire Script VS Single Line Runs
Show older comments
As the title states, I am getting different values from Matlab's length function depending on whether I run the entire script (Using the "Run" button) or just line by line manually. I have no clue why this is occuring but the Matlab functions are not producing correct results themselves when this occurs. I have Matlab on two seperate machines and tried testing the code on both and found the same issue persists. I tried simplifying the code with a very trvial example with the same input structures and the error does not apply to the simpler case. It is just occuring within my main code. For context, I am generating a custom mesh in cylindrical coordinates. The issue occurs on lines 104-105:
stemp = [length(nodesPhis) length(nodesPhiMSim)];
maxNodesPhi = max(length(nodesPhis),length(nodesPhiMSim)); % Finds the max dimension required for the
% phi-component 3D matrix to be populated
If we run the script using the run button, we can see in the variable window that the vector for stemp is [40,53]:
But when I highlight the text to manually run the line, it says [60,53]:

For context, I only define stemp once and in that line 104. Nowhere else is it redefined. Not only this, but even more contradictions come up later in the code from these lines. The code uses the max element of that vector to produce a NAN matrix with one of the dimensions lengths being that max number. This matrix is called "meshPhi", it's size is (x,max(stemp),z) and it is defined as:
meshPhi = NaN(length(nodesR),maxNodesPhi,max(length(nodesZ1),length(nodesZ2))); % Create "empty" phi-mesh to populate
When I run the code with the button, it actually creates the correctly sized meshPhi matrix:

But as can be seen, the meshR and meshZ matrices which are supposed to be the same size, are using 53, and not 60. Those matrices are defined like this on lines 142 and 156:
meshZ = NaN(length(nodesR),maxNodesPhi,max(length(nodesZ1),length(nodesZ2))); % Create "empty" z-mesh to populate
meshR = NaN(length(nodesR),maxNodesPhi,max(length(nodesZ1),length(nodesZ2))); % Create "empty" r-mesh to populate
Exactly the same... so the only thing I can think of is it seems that Matlab is bugged in some way here. Nonetheless, I still wanted to post this question to see if possibly it's not a bug and instead I am potentially missing something or not using an internal function correctly.
Main Code: "TEST_DynCylMesh.m"
Supporting function: "sigdigits.m"
15 Comments
dpb
on 19 Jun 2023
I didn't try to delve into the internals, but
stemp = [length(nodesPhis) length(nodesPhiMSim)];
is very fragile and error-prone code and I'd venture is the root cause of the issues.
length(x) is defined as max(size(x)) and so is dependent upon the size and orientation of the input array; it will return either size(x),1) or size(x),2) depending upon whether x has more rows or columns.
Rewrite your code to use the explicit size() direction you intend before spending any more time scratching your head over this; I strongly suspect the issue will disappear once done. Of course, also be certain to create arrays of the proper orientation when doing so...
John D'Errico
on 19 Jun 2023
If I had a dime for every time I have seen someone say that some code MUST be exposing a bug in MATLAB, I would be wealthy.
If I had to guess what is the problem, even without looking at that lengthy code in any depth, the first thing I would guess is that you did not fully clear your workspace, when you ran the code one line at a time.
John
on 19 Jun 2023
Image Analyst
on 19 Jun 2023
Well it actually was a bug, but a bug in your code, not MATLAB itself.
dpb
on 19 Jun 2023
" Those were defined as arrays so that's why I was using length and not size..."
That's precisely where length is dangerous; for vectors one dimension is always one; for arrays one can get either row or column size depending...
John
on 19 Jun 2023
length() probably wouldn't make it into the MATLAB stable if it were to be brought up as a new addition now; it existed in first releases as is and so is carried along for compatibility purposes, but really should be avoided owing to the above issues.
If one is extremely careful, one can get by, but it's very possible for an unexpected result to occur when/if data sizes change beyond those that were expected when the code was written. Simply reading an array that now has N+1 variables will return the column size where it is expected to be the row size if there are <=N observations. This case may have been thought to be impossible originally, but things changed.
IMO, the height(), width() functions for tables ought to be extended to accept matrices/arrays as wel(*)l...before they were introduced I built and keep in my Utilities folder nrows(), ncols() as syntax sugar for the size(x,1), size(x,2) idioms; I've suggested those should also be builtins, but has fallen on deaf ears for 30 year or more...
(*) Of course table is constrained to be a 2D object; trying to create an array of tables results in simply appending the table content instead so the English meaning of width and height is maintained whereas for arrays of more than three dimensions there's not such a correlation for the higher dimensions.
I notice that length() actually isn't defined for table objects although one can still use max(size(t)) to get the same end result (although I see no reason why one would want to do that given the problems outlined).
Steven Lord
on 19 Jun 2023
The length function may not have been approved for inclusion in MATLAB in its current form if it had been proposed today, though it might have passed design review if it were limited to returning the number of elements in a vector (as a shortcut for asserting that the input isvector and then returning numel of that vector.)
dpb
on 19 Jun 2023
Well, I'll be! I've continued to use R2020b to date rather than change horses in midstream of a major data manipulation exercise. Thanks for pointing it out...having my utility functions, I just automagically use them instead so I'd never thought to try it and if I noticed in the release notes, it never made it past the rote usage practice to the conscious level.
dpb
on 19 Jun 2023
I don't recall if any of the musings by Cleve on early versions included anything about why he designed length as did...probably there was a specific use in mind and it seemed like a good idea at the time.
Rik
on 19 Jun 2023
If you want the length of a vector, length does what it says on the tin. When you get to how people actually use it, dragons pop up around every corner.
Adding to the discussion at hand: I maintain that any code you want to use after next week should be in a function. That provides a stable interface that you can document. Of course this is a rule you can break, but only if you follow it first. Problem like this get a lot easier to track down.
I personally compose larger functions from parts (a poor man's package management), so I don't actually need to remember which functions do what. Sometimes I come across a function I wrote years ago. I usually need to wipe some tears and rewrite a lot of code, but only to improve style and performance (or to fix edge cases). The beauty of functions is that it works whether you wrote it terribly or well. And once you update, you shouldn't need to worry about other code depending on it, because every function is a black box to the functions calling it.
@Bruno Luong -- that's the edge case, yes.
The doc actually reads as " For arrays with more dimensions, the length is max(size(X)). The length of an empty array is zero." I did leave off the for zero-length arrays part, yes, since they weren't pertinent in this particular thread.
So strictly in compliance, the form would be max(size((x))*~isempty(x)
x=zeros(1,0);
length(x)
max(size(x))*~isempty(x)
Answers (0)
Categories
Find more on Matrix Indexing 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!