2015-04-11 2 views
1

Dans un code Fortran, j'ai un tableau a avec des valeurs allant uniformément de 0.0 à 1.2 et je cherche l'indice de la valeur qui est la plus proche de 1.0.Quelles sont les méthodes pour trouver l'élément d'un tableau contenant une valeur réelle spécifique?

Il ne semble pas y avoir de intrinsics de le faire en Fortran, donc je fait une solution de contournement hacky avec MINLOC: (notez que temp est la même forme que a)

do i=1,n 
    temp(i) = 1.0 - a(i) 
end do 
loc = 0 !note that loc is an integer array, declared as 'loc(1)' 
index_1 = minloc(abs(temp(:))) !this is the index of a closest to 1.0 

Cela semble faire l'astuce.

Je suis intéressé par d'autres méthodes pour y parvenir, ont donc quelques questions:

  • Comment fonctionne MINLOC?
  • Y a-t-il d'autres routines pour y arriver directement (c'est-à-dire sans avoir à faire un second tableau)?
  • Comment cela est-il géré dans d'autres langues?

Merci.


EDIT: je l'ai déjà lié à this article, citant motivation partielle de trouver des alternatives à MINLOC, mais ont retiré comme certains commentateurs ont souligné qu'il est un peu hors de propos. L'inclure a semblé nuire à mon but qui est de trouver des alternatives à cette méthode.

+1

Cet article de blog semble vraiment me comparer des pommes et des oranges. Les méthodes comparées font vraiment des choses différentes. Bien sûr, le premier sera le plus rapide s'il recherche une correspondance exacte et quitte tôt. Mais cela ne fonctionnera pas s'il n'y a pas de correspondance exacte. – skagedal

+0

Hm, merci d'avoir signalé cela, je vais éditer ma question. – Makkasu

Répondre

1

D'abord noter que l'article lié ne critique pas les performances de MINLOC lui-même, mais il critique les performances pour trouver une valeur particulière.

Dans Fortran 2008, il y a le FINDLOC intrinsèque à cette fin, mais ce n'est peut-être pas la bonne chose pour le problème. Ce serait cependant la bonne chose pour le problème dans l'article référencé. Voir aussi Fortran findloc intrinsic

L'une des raisons de la lenteur, qui est visible immédiatement, est qu'un tableau temporaire doit être créé pour abs(temp(:)) lors de l'appel MINLOC(abs(temp(:))). L'autre raison est que la boucle dans l'article peut quitter immédiatement, lorsque la correspondance est trouvée. Ce n'est cependant pas important pour votre application.

Le MINLOC intrinsèque n'est probablement pas lent, il recherche simplement le tableau dans une simple boucle.

Ces résultats différeront également parmi les compilateurs. Avez-vous vérifié la différence de performance pour votre compilateur?

Le dernier conseil: il suffit d'écrire une simple boucle qui évite le tableau temporaire.


Une simple boucle pour trouver l'élément en virgule flottante le plus proche. Truc simple CS101.

min_diff = huge(1.0) 
idx = 0 

do i = 1, size(a) 
    diff = abs(a(i)-to_find) 
    if (diff < min_diff) then 
    idx = i 
    min_diff = diff 
    end if 
end do 
+0

Merci pour la réponse détaillée, je n'avais pas entendu parler de 'findloc'. Je n'ai pas vérifié spécifiquement les performances de mon application, je m'intéressais simplement au fonctionnement de 'minloc' et aux autres méthodes que je pouvais utiliser. – Makkasu

+1

@Makkasu Différents compilateurs peuvent implémenter minloc différemment. Vous pouvez étudier l'implémentation du GCC sur https://gcc.gnu.org/viewcvs/gcc/trunk/libgfortran/m4/minloc1.m4?view=markup. C'est en fait une boucle très simple, vous pouvez l'écrire facilement vous-même. –

+0

@Makkasu Si vous vous intéressez à la performance, écrivez simplement une boucle très simple qui va d'un élément à un autre jusqu'à ce qu'elle trouve une correspondance, je n'ai pas vraiment ce que vous cherchez. –

1

Cela ne fonctionnera plus vite que votre solution, mais il raccourcit certainement le code:

index_1 = minloc(abs(a - 1)) 

Pendant que vous ne pas mettre en place un tableau temporaire vous de cette façon, le compilateur toujours faites-le dans les coulisses. MINLOC fonctionne par force brute: il n'y a pas de raccourci pour trouver un minimum.

Si vous avez besoin de rechercher des valeurs différentes à plusieurs reprises dans ce tableau, il serait beaucoup plus rapide de trier d'abord le tableau a, puis d'effectuer une recherche binaire. Cela réduira le temps d'exécution de O (n) à O (log (n)), où n est la taille de a.

+0

Merci pour la réponse, cela a éclairci quelques choses. Que voulez-vous dire par recherche binaire? – Makkasu

+1

[C'est ce que je veux dire.] (Http://en.wikipedia.org/wiki/Binary_search_algorithm) Disons que vous avez un tableau [1, 2, 3, 4, 5], et que vous voulez rechercher la valeur 5. Parce que le tableau est trié, il existe un meilleur algorithme que de simplement boucler les cinq valeurs du tableau. La recherche binaire coupe successivement le tableau en deux, puis regarde dans la moitié gauche ou la moitié droite, selon que la valeur moyenne est supérieure ou inférieure à la valeur 5 que vous recherchez. –

+0

Super, ça a du sens, merci. – Makkasu