subtracting elements in a vector

37 visualizaciones (últimos 30 días)
Nikolas Spiliopoulos
Nikolas Spiliopoulos el 25 de Feb. de 2017
Editada: John D'Errico el 25 de Feb. de 2017
hi all,
an easy question for you:
I have a vector A= [0 1 4 10 18] how can I subtract the second element from the first, the third from the second ans so on? The final vector I would be to be=[1 3 7 11]
thanks!

Respuesta aceptada

Guillaume
Guillaume el 25 de Feb. de 2017
Editada: Guillaume el 25 de Feb. de 2017
diff(A)
which will result in [1 3 6 8] not [1 3 6 12]
  4 comentarios
Guillaume
Guillaume el 25 de Feb. de 2017
Alright, that's a completely different question
result = filter(1, [1, 1], A)
result = result(2:end)
Nikolas Spiliopoulos
Nikolas Spiliopoulos el 25 de Feb. de 2017
thanks a lot !!

Iniciar sesión para comentar.

Más respuestas (1)

John D'Errico
John D'Errico el 25 de Feb. de 2017
Editada: John D'Errico el 25 de Feb. de 2017
A for loop is always a viable solution to a problem when you see no easier way out. And a single for loop is not terribly inefficient. It is when you have doubly, triply nested loops that you usually want to look for a better, vectorized solution. So, first, how might I do this using a simple loop?
A= [0 1 4 10 18];
% initialize the result to the correct size,
% as well as compute the difference of the first pair
D = diff(A);
for k = 3:numel(A)
D(k-1) = A(k) - D(k-2);
end
D
D =
1 3 7 11
So the simple loop works. It is often the case where a loop is a good solution. In fact, looking for a less obvious, vectorized solution is not always worth the time to work it out. Only worry about vectorizing code where you know it will be valuable. Computer time is far cheaper than programmer time. As you improve in skill, you learn what operations are best done in a vectorized manner. You will then usually recognize those cases immediately, knowing when to loop, when to use vectorized code.
So lets first expand the problem. A little pencil and paper algebra should yield this as the result, enough for us to see the pattern:
[A2 - A1, A1 - A2 + A3, A2 - A1 - A3 + A4, A1 - A2 + A3 - A4 + A5]
We can now write some basic, vectorized code that will suffice, for a 5 element vector. I'll write some things out so that you can see the pattern.
syms A1 A2 A3 A4 A5
A = [A1,A2,A3,A4,A5];
D = cumsum(A.*[1 -1 1 -1 1])
D =
[ A1, A1 - A2, A1 - A2 + A3, A1 - A2 + A3 - A4, A1 - A2 + A3 - A4 + A5]
So if I look at the vector D, it looks very close to what I wrote above. With one more change, we have it:
D = D(2:end).*[-1 1 -1 1]
D =
[ A2 - A1, A1 - A2 + A3, A2 - A1 - A3 + A4, A1 - A2 + A3 - A4 + A5]
So, now can we write this in a form that will work on any vector, and do so without an explicit loop?
A = [0 1 4 10 18];
n = numel(A);
D = cumsum(A.*(mod(1:n,2)*2-1));
D = D(2:end).*(1-mod(1:n-1,2)*2);
Did it work? Of course it worked. Does it hurt my brain to look at it? Yes, because it is not at all obvious what it does.
D
D =
1 3 7 11
Was it worth the time spent to do this? Probably not, unless it is something you will do tremendously often. Otherwise, this is a case of optimization for no good purpose, because if you actually wanted to understand what those lines that I wrote did, it would take some effort to work it out, just as I did above.
Were I to use the vectorized code in my own work, I would add extensive comments that explain the exact purpose of the vectorized code, and how it works. That way, when I revisit the code a year later, I will have a chance of understanding it.
Finally, with some thought, we could probably write code for this that will work using the function filter. Since we already have a simple solution that is vectorized, why bother? Remember that programming elegance is not always worth the investment of programmer time.
Edit: The filter solution is:
D = filter(1,[1 1],A);
D(1) = [];
D
D =
1 3 7 11
  2 comentarios
Stephen23
Stephen23 el 25 de Feb. de 2017
Editada: Stephen23 el 25 de Feb. de 2017
+1: Thank you John D'Errico: as always you provide a very good read, and a few insights in effective strategies for writing good code. Much appreciated!
John D'Errico
John D'Errico el 25 de Feb. de 2017
TY Stephen.
As I thought, there is a simple solution that employs filter.
D = filter(1,[1 1],A);
D(1) = [];
D
D =
1 3 7 11
This solution may be obvious to some. Others will need to puzzle over the filter documentation. I admit that I had to read the help to determine the correct filter coefficients, even though I knew that filter could solve the problem. So, IF you do choose to use a solution like this, you may be advised to add comments explaining what it does.
Again, a simple loop is not always a bad thing.

Iniciar sesión para comentar.

Etiquetas

Community Treasure Hunt

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

Start Hunting!

Translated by