This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 5 years ago.
I'm having trouble summing 3 double numbers in MATLAB Command Window, here are my variables
>> a = 0.45;
>> b = 0.05;
>> c = -0.5;
when I sum them like this, I get 1.3878e-17
>> c + a + b
ans =
1.3878e-17
But when I use parentheses, it returns 0
>> c + (a + b)
ans =
0
Also summing them in this order returns 0 again
>> a + b + c
ans =
0
In usual storage of floats in programming languages using IEEE 754. Therefore, for storage of some floating numbers which cannot be shown by sum of some 2^i, there wouldbe some errors (in base 2) such as 0.3.
As mentioned in comments, you can use digits to find these errors:
digits(100);
vpa(a)
>> 0.4500000000000000111022302462515654042363166809082031250000000000000000000000000000000000000000000000
vpa(b)
>> 0.05000000000000000277555756156289135105907917022705078125000000000000000000000000000000000000000000000
vpa(c)
>> -0.5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
vpa(a+b)
>> 0.5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
vpa(c+a)
>> -0.04999999999999998889776975374843459576368331909179687500000000000000000000000000000000000000000000000
As you can see in the above, because of this error, sum of a and c is not as exactly as you've expected (because of error in storage of floating points in base 2 in IEEE 754).
Therefore, there order of + is important as you found through these expressions. Hence, the preference of plus is from left to right, and preference of parenthesis is higher than plus, in the c + (a + b) and a + b + c, the a + b is done first,. Then, you can see the sum is exact in the above. However, in c + a + b, the c + a is happened sooner and you can see this sum is not exact, so the result of this sum with b could have some error.
In this way, you can find a + c + b is not exact as you want. And:
vpa(c + b)
>> -0.4500000000000000111022302462515654042363166809082031250000000000000000000000000000000000000000000000
So,
c + b + a
>> 0
Related
Does anyone know why this works in MATLAB?
>> 1 ++ 2
ans =
3
Coming from coding in C, python, Java etc, I find it most counterintuitive that this should work at all. Presumably there's something important about the parser that I don't understand?
There's a difference between plus and uplus. I suspect MATLAB takes the first + as plus, and all the others as uplus. Since uplus is by default just "return what's behind", you add 1 and 2, and use a lot of "return what's behind" in between.
a=2;
c=+a % unitary plus
c =
2
1+2 % addition
ans =
3
1+++2 % addition and two uplusses
ans =
3
The reason uplus exists is to allow operator overloading in classes. The same works in other languages, e.g. in C#, to allow for operator overloading in confined classes.
The other reason mentioned in that C# thread is that is changes unsigned shorts to integers, which is not the case for MATLAB:
d=uint8(1)
d =
uint8
1
+d
ans =
uint8
1
a=+d
a =
uint8
1
It does, however, convert a boolean to a double, thanks to Cris Lunego for pointing that out:
+true
ans =
1
+false
ans =
0
The following however remains a mystery to me, inspired by Sanjay Manohar's comment:
>> [1 ++ 2]
ans =
1 2 % Two unary plusses
>> [1 + + 2]
ans =
3 % A normal plus and a unary one
>> [1++2]
ans =
3 % A normal plus and a unary one
The same works with multiple plusses, [1 +++..+++ 2], so with all plusses consecutively in the middle generates [1 2], all other combinations (as far as I tested) result in 3. I asked a separate question about this: Why do the plus and unary plus behave strange in array syntax?
i'm a beginner in matlab and i want to calculate the sum of product of every possible combination of elements of a (3*n) matrix that are picked from different row.
for example if the matrix is x = [1 2 3 , 4 5 6] i want the result of
D = 1*4 + 1*5 + 1*6 + 2*4 + 2*5 + 2*6 + 3*4 + 3*5 + 3*6.
I wrote the following recursive code but i'm having problem with passing a variable by reference.
function combination(n,A,x) % n= number of rows ,A= empty array, x = the matrix
if n == 0
D = D + prod(A);
else
for i = 1:1:3
A = [A x(n,i)];
combination(n-1,A,x);
if length(A)>=1
A = A(1:length(A)-1);
end
end
end
end
i need the D parameter but when i declare D as global it doesn't help.
is there anyway in matlab that i could pass D by reference in function and get the result at the end?
thanks in advance.
sorry for my english.
Can you just use prod(sum(x,2))? I think if you rearrange the terms in your sum, you'll see that you can just multiply the sums of your rows together and you'll get the same thing. (But perhaps I've misunderstood exactly what you're looking for).
For example:
>> x=[1 2 3 ; 4 5 6; 7,8,9]
x =
1 2 3
4 5 6
7 8 9
>> prod(sum(x,2))
ans =
2160
>> 1*4*7 + 1*4*8 + 1*4*9 + 1*5*7 + 1*5*8 + 1*5*9 + 1*6*7 + 1*6*8 + 1*6*9 + 2*4*7 + 2*4*8 + 2*4*9 + 2*5*7 + 2*5*8 + 2*5*9 + 2*6*7 + 2*6*8 + 2*6*9 + 3*4*7 + 3*4*8 + 3*4*9 + 3*5*7 + 3*5*8 + 3*5*9 + 3*6*7 + 3*6*8 + 3*6*9
ans =
2160
If you really need to do this recursively, using a combinatory approach, you should be able to just pass in D as an input and also return it as an output of your function, something like this:
function D = combination(n,A,x, D) % n= number of rows ,A= empty array, x = the matrix
if n == 0
D = D + prod(A);
else
for i = 1:1:3
A = [A x(n,i)];
D = combination(n-1,A,x, D);
if length(A)>=1
A = A(1:length(A)-1);
end
end
end
end
and then call it initially with D equal to zero.
Don't worry about passing by reference here. MATLAB doesn't have pass by reference (it has variables that have reference semantics, but that's a different thing), but it uses copy-on-write, and has special optimizations for calculations that can be done in-place, as your calculation with D can here.
Declaring it as global does the job, however, you should pass it as input, and return it as output.
MATLAB will take care of not making a copy if your code does not need a copy of it.
If you write in the function definition:
function D = combination(n,A,x,D)
D = D + something
end
your function can be called by:
output = combination(n_in,A_in,x_in
the recursion follows the same so instead of calling
combination(n-1, A,x)
you write
D = combination(n-1,A,x,D)
and go on in your code.
I hope this helps you, and maybe there is a Matlab own function that can handle this task already but I am not sure.
This question already has an answer here:
Rounding to n significant digits
(1 answer)
Closed 5 years ago.
When you try rounding a symbolic expression to N digits you get the error messages below:
>> format long
>> syms x;
>> round(x, 10)
Error using sym/round
Too many input arguments.
>> round(vpa(pi), 10)
Error using sym/round
Too many input arguments.
So how do you make this work ?
Here it is how you do
>> syms x; N = 6;
>> round(pi*10^N)/vpa(10^N)
ans =
3.141593
>> round(x*10^N)/vpa(10^N)
ans =
0.000001*round(1000000*x)
It is just a simple case in matlab, something strange about function subs() happens and I don't know why.
I have read the official help doc and googled the error message but didn't find useful information.
Could someone tell me what wrong the the command "subs(f)"?
>> syms x w b f
>> f=x*w-b
f =
w*x - b
>> w=[1 2 3 ;4 5 6; 7 8 9 ]
w =
1 2 3
4 5 6
7 8 9
>> x=[1 2 3.44]'
x =
1.0000
2.0000
3.4400
>> b=[ 2 4 7 ]'
b =
2
4
7
>> f
f =
w*x - b
>> subs(f)
Error using symengine
New arrays must have the same dimensions or must be scalars.
Error in sym/subs>mupadsubs (line 140)
G = mupadmex('symobj::fullsubs',F.s,X2,Y2);
Error in sym/subs (line 125)
G = mupadsubs(F,X,Y);
here is a screenshot of the error message:
The Symbolic Toolbox operates from the standpoint that Symbolic Variables are scalars and any operation or expression in which they are present uses element-wise semantics. As states in the subs documentation:
If old is a scalar, and new is a vector or matrix, then subs(s,old,new) replaces all instances of old in s with new, performing all operations elementwise. All constant terms in s are replaced with the constant times a vector or matrix of all 1s.
So the expression undergoing substitution needs to play nice with element-wise application and expansion upon substitution. However, when the new arrays being substituted do no match size in every dimension (as is the case here with the coefficient matrix being rectangular versus the column vector), a dimension mismatch will more than likely occur in the engine. Even direct specification of the substitution with cell arrays throws the error:
>> wnum = [1 2 3 ;4 5 6; 7 8 9 ];
>> xnum = [1 2 3.44]';
>> bnum = [ 2 4 7 ]';
>> subs(f,{w,x,b},{wnum,xnum,bnum})
Error using symengine
New arrays must have the same dimensions or must be scalars.
Error in sym/subs>mupadsubs (line 140)
G = mupadmex('symobj::fullsubs',F.s,X2,Y2);
Error in sym/subs (line 125)
G = mupadsubs(F,X,Y);
While fully conforming dimensional substitutions will work just fine:
>> subs(f,{w,x,b},{xnum,xnum,xnum}); % All 3x1
>> subs(f,{w,x,b},{wnum,wnum,wnum}); % All 3x3
And all of this derives from the Symbolic Variables themselves being treated as scalars. The Symbolic work-around being to declare the variables as Symbolic Arrays to generate the individual elements of the arrays and allow for a one-to-one substitution:
>> w = sym('w',[3,3]);
>> x = sym('x',[3,1]);
>> b = sym('b',[3,1]);
>> f = w*x - b;
>> subs(f,[w,x,b],[wnum,xnum,bnum])
ans =
333/25
766/25
1174/25
Of course, the best course of action, if you can do so, is to avoid the Symbolic Toolbox entirely or as much as possible.
>> double(subs(f,[w,x,b],[wnum,xnum,bnum]))
ans =
13.3200
30.6400
46.9600
>> fnum = wnum*xnum - bnum
fnum =
13.3200
30.6400
46.9600
The above discussion is a very, very large reason as to why I leave Linear Algebra to the MATLAB run-time proper, aside from all of the performance increases associated with it. The Symbolic Toolbox, in my opinion, is best left to analysis of functions in one or more variables (I use it to create Taylor Series, Jacobians, and Hessians often enough) or high precision analysis of a small dimensional problem for investigative purposes.
I want to automatically calculate expansions of polynomials where there are variables (x1,x2,...) as well as coefficients (c1,c2, ...). My goal is to calculate p(1)*(c1*x1+c2*x2+...)^n+ ... + p(n)*(c1*x1+c2*x2+...)^n .
As you can notice the resulting expression can be written as F(x1,x2...)*g(c1,c2,...) [where F is a row matrix and g is column matrix], i.e. there is some multiplicative decoupling between the coefficients and the variables.
Right now I use the MATLAB symbolic toolbox and construct F and g by manually examining the resulting symbolic expansions. This is not very feasible as if n is big and c=(c1,c2,...) is too big there are too many terms and it is no longer possible manually. For instance for (c1*x1+c2*x2+c3) and n=2, what I want is following.
>> p=[2 5]
p =
2 5
>> syms c1 c2 c3
>> syms x1 x2
>> expression= p(1)*(c1*x1+c2*x2+c3)^2 + p(2)*(c1*x1+c2*x2+c3);
>> expand(expression)
ans =
2*c1^2*x1^2 + 4*c1*c2*x1*x2 + 4*c1*c3*x1 + 5*c1*x1 + 2*c2^2*x2^2 + 4*c2*c3*x2 + 5*c2*x2 + 2*c3^2 + 5*c3
>> F=[5*x1 5*x2 5 4*x1*x2 4*x1 4*x2 2*x1^2 2*x2^2 2]
F =
[ 5*x1, 5*x2, 5, 4*x1*x2, 4*x1, 4*x2, 2*x1^2, 2*x2^2, 2]
>> g=[c1 c2 c3 c1*c2 c1*c3 c2*c3 c1^2 c2^2 c3^2].'
g =
c1
c2
c3
c1*c2
c1*c3
c2*c3
c1^2
c2^2
c3^2
>> expand(F*g)
ans =
2*c1^2*x1^2 + 4*c1*c2*x1*x2 + 4*c1*c3*x1 + 5*c1*x1 + 2*c2^2*x2^2 + 4*c2*c3*x2 + 5*c2*x2 + 2*c3^2 + 5*c3
I have found the following question and it looks like there may be a way to do it automatically using conv etc. If one can come up with an automated solution (or at least some idea towards such automation) for the case where x=(x1,x2) and c=(c1,c2,c3) and n=2, the case depicted above; I guess I may be able to generalize it to higher dimensional cases.
Note: the ordering of terms in F or g does not matter, given that they are ordered in some structured way.
The coefficients from different terms don't overlap. The first term, p(1)*(c'*x)^1, has only terms of degree 1 in xi and ci, and so on. So it becomes a matter of computing the coefficients of one term at a time.
That, too, has a "simple" expression:
p(k)*(c'*x)^k = sum(i1,..,im>=0 with sum(i_)=k)
M(k;i1,..,im)*x1^i1*...*xm^im * c1^i1*...*cm^im
where the summation is such that the sum of all i equals k, and M is the multinomial coefficient.
For m=3, n=2, the i's would be in the order of your example: 110,101,011,200,020,002. M(2;110)=2 so the first term is `p(2)*M(2;110)*x1*x2 = 4*x1*x2'.
Your F and g terms are:
F(...) = p(k)*M(k;i1,..,im)*x1^i1*...*xm^im
g(...) = c1^i1*...*cm^im