Je normalise un vecteur V dans MATLAB comme suit:
normalized_V = V/norm(V);
Cependant, est-ce la manière la plus élégante (efficace) de normaliser un vecteur dans MATLAB?
Je normalise un vecteur V dans MATLAB comme suit:
normalized_V = V/norm(V);
Cependant, est-ce la manière la plus élégante (efficace) de normaliser un vecteur dans MATLAB?
Le code d'origine que vous suggérez est le meilleur moyen.
Matlab est extrêmement bon pour vectorisé opérations comme celle-ci, au moins pour les grands vecteurs.
Intégré dans la norme de la fonction est très rapide. Voici quelques résultats de minutage:
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 est calculé un deuxième temps, ici, juste pour s'assurer que il n'y a pas importante cache des sanctions sur le premier appel.
Des informations de synchronisation ici a été réalisé avec R2008a x64 sur Windows.
EDIT:
Révisé réponse repose sur gnovice suggestions (voir les commentaires). Matrice de mathématiques (à peine) gagne:
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
À mon humble avis, la différence entre "norm(V)" et "sqrt(V'V)" est assez petit pour que pour la plupart des programmes, il est préférable d'aller avec celui qui est plus clair. Pour moi, "norm(V)" est plus clair et plus facile à lire, mais "sqrt(V'V)" est toujours idiomatiques dans Matlab.
Le seul problème que vous rencontrerez est de savoir si la norme de V est nul (ou très près). Cela pourrait vous donner Inf ou NaN lorsque vous divisez, avec une division par zéro avertissement. Si vous n'avez pas de soins sur l'obtention d'un Inf ou NaN, vous pouvez simplement activer l'avertissement à l'aide d'AVERTISSEMENT:
oldState = warning('off','MATLAB:divideByZero'); % Return previous state then
% turn off DBZ warning
uV = V/norm(V);
warning(oldState); % Restore previous state
Si vous ne voulez pas de Inf ou NaN valeurs, vous devez vérifier la taille de la norme en premier:
normV = norm(V);
if normV > 0, % Or some other threshold, like EPS
uV = V/normV;
else,
uV = V; % Do nothing since it's basically 0
end
Si j'en ai besoin dans un programme, j'ai l'habitude de mettre le code ci-dessus dans mon propre fonction, appelée généralement de l'unité (car il s'avère en fait un vecteur en un vecteur unitaire pointant dans la même direction).
J'ai pris le code de M. Fooz et également ajouté la solution d'Arlen. Voici les temps que j'ai obtenus pour 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
Ensuite, à cause de quelque chose que je suis en train de regarder, j'ai testé ce code pour vérifier que chaque rangée vaut 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
Par le rationnel de tout multiplier j'ajoute l'entrée à la fin de la liste
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
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.