How to prevent adding a number to a matrix elements?
Show older comments
in matlab if we have an matix like A[n,n], when we add a scalar value (b) to it, solve it like this:
A+b*ones(n)
but i want if in my cod exist addition like A+b, matlab dont add an scalar num to matrix and show error, is any way to do it?
for example
A=[1 2;3 4]
b=3
in fact A is 2 by 2 matrix and b is 1 by 1 and they should not added with together but matlab change b as a 2 by to matrix then solve (A+b*ones(2)) as
ans=[4 5;6 7]
but i want to matlab return error mismatch matrix dimensions.
Answers (3)
Jan
on 27 Nov 2017
The auto-expanding of scalars is a typical feature of Matlab since it has been created. This behavior can and should not be changed in general. But you can write your own functions for addition:
function c = xPlus(a, b)
if isequal(size(a), size(b))
c = a + b;
else
error('ExtraOPs:xPlus:SizeMismatch', 'Sizes of inputs do not match.');
end
end
Then:
A = [1 2;3 4]
b = 3
C = xPlus(A, b)
% >> Error message
Or maybe more general:
function SameSize(a, b)
if ~isequal(size(a), size(b))
error('ExtraOPs:SameSize:Mismatch', 'Sizes of inputs do not match.');
end
end
Then:
A = [1 2;3 4]
b = 3
SameSize(A, b);
C = A + b
This is much better then trying to overload the built-in operators, which would confuse Matlab's toolbox functions and many other 3rd party codes.
4 Comments
mohammad m
on 28 Nov 2017
Walter Roberson
on 28 Nov 2017
Edited: Walter Roberson
on 28 Nov 2017
Then you will need to subclass like I posted before. It would look something like,
A = NoExpansionArray([1 2; 3 4]); %Make A a member of your class
b = NoExpansionArray(3);
c = A + b;
where NoExpansionArray has been defined something like
classdef NoExpansionArray < double
methods
function obj = plus(first, second)
if ~isa(first, 'NoExpansionArray') || ~isa(second, 'NoExpansionArray')
error('Both operands must be NoExpansionArray for addition');
end
if ~isequal(size(first), size(second))
error('Do not add NoExpansionArray of different sizes');
end
obj = builtin('plus', first, second);
end
function obj = minus(first, second)
if ~isa(first, 'NoExpansionArray') || ~isa(second, 'NoExpansionArray')
error('Both operands must be NoExpansionArray for subtraction');
end
if ~isequal(size(first), size(second))
error('Do not subtract NoExpansionArray of different sizes');
end
obj = builtin('minus', first, second);
end
end
The above is untested.
Jan
on 29 Nov 2017
using function confuse me
Then this might be the best point to start from. Inserting a "SameSize(A, b)" does not look too confusing and a reader knows the purpose immediately. It might be more confusing for a person who is familiar with Matlab to see "A + b" failing for a scalar b.
mohammad m
on 30 Nov 2017
Edited: mohammad m
on 1 Dec 2017
Jos (10584)
on 28 Nov 2017
1 vote
Many, if not all, functions rely on scalar expansion to happen for the plus operator. I strongly suggest you either get used to this behaviour of MatLab, or use a function to test explicitly for the same size of the two operants before you execute the addition (as Walter and Jan already suggested).
10 Comments
Guillaume
on 28 Nov 2017
I strongly suggest you either get used to this behaviour
+1. I'm going to be even more brutal and say that if you cannot get used to this behaviour then matlab is not the right tool for you. Trying to make matlab conform to some completely opposite behaviour is a fool's errand.
Walter Roberson
on 28 Nov 2017
... though I still think there ought to be a way to turn off the new (R2016b) implicit expansion as a debugging tool.
Jos (10584)
on 28 Nov 2017
I second that, Walter. Bugs turning into features are, occasionally, quite annoying :)
Jan
on 29 Nov 2017
@Walter: I agree. I do like the expansion, because it improves the readability of many codes. But the "auto" remains a problem. It would have been very nice to implement an "intentional-expanding" by e.g. ":+", ":-", ":*", ":/" and so on. This has the disadvantage, that the code is not backward compatible anymore.
Adam
on 30 Nov 2017
":/"
certainly seems appropriate for behaviour that ought to give an error but is now a feature!
Jos (10584)
on 30 Nov 2017
Edited: Jos (10584)
on 30 Nov 2017
I foresee all kind of new weird bugs here :)
1:+3 → [1 2 3] or 4?
Stephen23
on 30 Nov 2017
A character that is not otherwise used much in MATLAB:
$+
$-
$*
etc
Jan
on 30 Nov 2017
@Jos: You are right, ":+" fails in "1:+3". There are more unused characters: §$&?# or the auto-expand classifier can be appended: +:
Nevertheless, MathWorks decided unfortunately to stay at the standard operators and I expect that this will not be changed anymore. We asked for a dwim operator for so many years, now we got a operator-less dwim behavior.
Guillaume
on 30 Nov 2017
Personnaly, I like the new implicit expansion because it makes the language more consistant. Before, you had special cases which frankly should never have been allowed.
Now: you can perform binay operations if corresponding dimensions are the same or one of them is 1.
Before: you can perform binay operations if corresponding dimensions are the same, OR one input is scalar, OR both inputs have at most one dimension greater than 1 (i.e both are vectors in possibly different dimension).
Special cases in a language grammar are always bad. You can't write generic code anymore. It'd be great if similar special cases for vectors were removed from other functions as well (sum, A(B), etc.)
Jan
on 30 Nov 2017
@Guillaume: The auto-expanding did not cause any problems in my code, because I never relied on catching errors, if the sizes of the inputs are not matching. I find
v = 1:10;
M = v + v.'
nicer than
M = bsxfun(@plus, v, v.')
But I have used a C-Mex function since Matlab 5.3 already to perform this:
M = Expand(v, '+', v.')
I used BLAS libraries and unfolded loops for the standard cases [1 x N] and [M x 1]. In some cases this this is even faster than BSFXUN, but the auto-expansion is harder to beat.
With this groundwork, it was easy to adjust my code to auto-expanding: Simply search for "Expand(" and replace the pattern to get:
% M = Expand(v, '+', v.'); %@:ExpandConverted
AssertMatchSize(v, v.'); %@:Debug
M = v + v.'; %@:Auto-Expand >= R0216b
Finally I use a tool, which comments/uncomments all lines containing the key "%@:Debug" automatically (Brrrr, ugly like a C-preprocessor, but such useful :-) ). The "%@:ExpandConverted" allows to track or undo all changes automatically also.
But as soon as a programmer wrote (what I never did):
try
c = a + b;
catch % Reply NaN for not matching sizes:
c = NaN;
end
the auto-expanding kills the code and it could cost many many many hours of debugging and modifying the code - including testing the software afterwards again exhaustively.
The magic comments based on a unique key are powerful for maintaining larger projects (some hundred thousands lines of code), but of course this is ugly as all meta-programming methods. I use this method, because it let me convert all my codes to run with or without auto-expansion in a minute. But of course it is even easier to let it produce code, which does not run at all.
Sorry, I left the topic. This does not help Mohammad M anymore.
Walter Roberson
on 27 Nov 2017
0 votes
You could perhaps subclass the appropriate numeric types https://www.mathworks.com/help/matlab/matlab_oop/subclassing-matlab-built-in-classes.html redefining the plus() and minus() methods to detect scalar addition and error out. This would require that you deliberately make your matrix a member of the appropriate type and that you are careful about how you assign values.
1 Comment
mohammad m
on 27 Nov 2017
Categories
Find more on Code Execution 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!