How to normalize a vector in MATLAB effectively? Any built-in function?

I normalize the vector V in MATLAB as follows:

normalized_V = V/norm(V); 

however, is it the most elegant (efficient) way to normalize a vector in MATLAB?

+44
performance vector matlab
Jun 30 '09 at 0:53
source share
6 answers

The source code you offer is the best way.

Matlab is extremely good at vectorized operations such as this, at least for large vectors.

The built-in normal function is very fast. Here are some sync results:

 V = rand(10000000,1); % Run once tic; V1=V/norm(V); toc % result: 0.228273s tic; V2=V/sqrt(sum(V.*V)); toc % result: 0.325161s tic; V1=V/norm(V); toc % result: 0.218892s 

V1 is computed a second time here to make sure that there are no important cache penalties on the first call.

Sync information here was released with the R2008a x64 on Windows.




EDIT:

Revised answer based on gnovice suggestions (see comments). Matrix math (barely) wins:

 clc; clear all; V = rand(1024*1024*32,1); N = 10; tic; for i=1:N, V1 = V/norm(V); end; toc % 6.3 s tic; for i=1:N, V2 = V/sqrt(sum(V.*V)); end; toc % 9.3 s tic; for i=1:N, V3 = V/sqrt(V'*V); end; toc % 6.2 s *** tic; for i=1:N, V4 = V/sqrt(sum(V.^2)); end; toc % 9.2 s tic; for i=1:N, V1=V/norm(V); end; toc % 6.4 s 

IMHO, the difference between "norm (V)" and "sqrt (V '* V)" is small enough that for most programs it is best to go with what is more understandable. For me, "norm (V)" is more understandable and easier to read, but "sqrt (V '* V)" is still idiomatic in Matlab.

+39
Jun 30 '09 at 2:10
source share

I do not know any MATLAB, and I never used it, but it seems to me that you share. What for? Something like this will be much faster:

 d = 1/norm(V) V1 = V * d 
+15
Mar 30 '11 at 18:29
source share

The only problem you are facing is that the norm of zero V is zero (or very close to it). This can give you Inf or NaN when you split along with the division by zero warning. If you do not want to receive Inf or NaN , you can enable or disable the warning using WARNING :

 oldState = warning('off','MATLAB:divideByZero'); % Return previous state then % turn off DBZ warning uV = V/norm(V); warning(oldState); % Restore previous state 

If you do not need Inf or NaN values , first check the size of the norm:

 normV = norm(V); if normV > 0, % Or some other threshold, like EPS uV = V/normV; else, uV = V; % Do nothing since it basically 0 end 

If I need this in a program, I usually put the above code in my own function, usually called unit (since it basically turns the vector into a unit vector pointing in the same direction).

+9
Jun 30 '09 at 1:20
source share

I took Mr. Foose's code, and also added Arlene's solution, and here are the timings I received for Octave:

 clc; clear all; V = rand(1024*1024*32,1); N = 10; tic; for i=1:N, V1 = V/norm(V); end; toc % 7.0 s tic; for i=1:N, V2 = V/sqrt(sum(V.*V)); end; toc % 6.4 s tic; for i=1:N, V3 = V/sqrt(V'*V); end; toc % 5.5 s tic; for i=1:N, V4 = V/sqrt(sum(V.^2)); end; toc % 6.6 s tic; for i=1:N, V1 = V/norm(V); end; toc % 7.1 s tic; for i=1:N, d = 1/norm(V); V1 = V*d;end; toc % 4.7 s 

Then, due to the fact that I am currently browsing, I tested this code to ensure that each row is summed to 1:

 clc; clear all; m = 2048; V = rand(m); N = 100; tic; for i=1:N, V1 = V ./ (sum(V,2)*ones(1,m)); end; toc % 8.2 s tic; for i=1:N, V2 = bsxfun(@rdivide, V, sum(V,2)); end; toc % 5.8 s tic; for i=1:N, V3 = bsxfun(@rdivide, V, V*ones(m,1)); end; toc % 5.7 s tic; for i=1:N, V4 = V ./ (V*ones(m,m)); end; toc % 77.5 s tic; for i=1:N, d = 1./sum(V,2);V5 = bsxfun(@times, V, d); end; toc % 2.83 s tic; for i=1:N, d = 1./(V*ones(m,1));V6 = bsxfun(@times, V, d);end; toc % 2.75 s tic; for i=1:N, V1 = V ./ (sum(V,2)*ones(1,m)); end; toc % 8.2 s 
+3
Apr 10 2018-12-12T00:
source share

Rationally do all the multiplication, I add an entry at the end of the list

  clc; clear all; V = rand(1024*1024*32,1); N = 10; tic; for i=1:N, V1 = V/norm(V); end; toc % 4.5 s tic; for i=1:N, V2 = V/sqrt(sum(V.*V)); end; toc % 7.5 s tic; for i=1:N, V3 = V/sqrt(V'*V); end; toc % 4.9 s tic; for i=1:N, V4 = V/sqrt(sum(V.^2)); end; toc % 6.8 s tic; for i=1:N, V1 = V/norm(V); end; toc % 4.7 s tic; for i=1:N, d = 1/norm(V); V1 = V*d;end; toc % 4.9 s tic; for i=1:N, d = norm(V)^-1; V1 = V*d;end;toc % 4.4 s 
+2
Jul 30 '12 at 18:27
source share

Fastest (time compared to Jacobs):

 clc; clear all; V = rand(1024*1024*32,1); N = 10; tic; for i=1:N, d = 1/sqrt(V(1)*V(1)+V(2)*V(2)+V(3)*V(3)); V1 = V*d; end; toc % 1.5s 
0
Feb 12 '13 at 3:57
source share



All Articles