2009-10-14 7 views
1

Tenir compte de l'équation ci-dessous:Comment trouver la valeur de l'exposant dans Ruby?

2 ** n = A

Supposons A = 64.

Quelle est la manière la plus simple de trouver la valeur de n?

J'utilise actuellement selon deux approches

A= 64; n = 1; n+=1 while (A >> n) > 0; n-1 

A= 64; n = 0; n+=1 until (A == (2 ** n));n 

Y at-il une meilleure approche?

Autre façon d'exprimer le même problème:

2 = racine nième A Si je connais la valeur de A, comment puis-je déterminer la valeur de n?

+0

J'ai fait un benchmark simple sur trois approches. Comme prévu, l'approche logarithmique est la plus rapide. système utilisateur au total réel bit sage décalage à droite 0,235000 0,000000 0,235000 (0,235000) séquentielle compare 1,484000 0,000000 1,484000 (1,500000) logarithmique 0,141000 0,000000 0,141000 (0,140000) –

+1

J'ai changé la logique de la méthode de changement de décalage de bits (ie ma première approche) et a obtenu la meilleure performance par rapport aux trois autres méthodes. A = 64; n = 0; n + = 1 jusqu'à ((A >> = 1) == 0); n; Donc, je vais avec l'approche de décalage de bits. –

Répondre

4

Aucune des réponses ci-dessus est mieux que votre première approche:

A= 64; n = 1; n+=1 while (A >> n) > 0; n-1 

Évaluer Math.log(x) prend beaucoup plus de temps que de faire une douzaine de bits, et vous donnera également une réponse comme 5.99999999999980235 pour donner un sens à.

Voir this SO question pour de meilleures idées.

3

log n = ln n/ln 2

donc

log_2_64 = Math.log(64)/Math.log(2) 
9

Essayez ceci:

def exp_value(n) 
    Math.log(n)/Math.log(2) 
end 
+0

Des trucs comme ça me font souhaiter que je comprenne bien les logarithmes, que je connaisse de bonnes/simples références en ligne? –

+2

Ce n'est pas des mathématiques complexes - ils enseignent cela au lycée: http://en.wikipedia.org/wiki/Logarithm – duffymo

+4

@Duffymo: assez juste mais (1) complexe (ou pas) est un terme relatif ici et (2) nous n'avons pas tous prêté attention pendant les cours de mathématiques au lycée. Il n'y a aucun sens à dire à quelqu'un, «c'est trivial», s'il demande des références à plus d'informations. – Telemachus

-1

Si vous vous intéressez à problems mentioned by mobrule. Que dis-tu de ça? C'est la même chose que votre propre méthode, mais utilisez la fonction intégrée pour communiquer l'idée de façon explicite.

def exp_value a 
     (1..a).to_a.detect {|n| 2**n >=a} 
    end 

    exp_value 64 
    => 6 
+0

(1..a) .to_a crée un tableau de taille a. Donc, votre algorithme a une complexité O (n) pour quelque chose qui pourrait être atteint beaucoup plus efficacement ... – Lykos

+0

Il a fallu plusieurs secondes sur mon ordinateur pour des nombres comme 10 millions, qui sont assez petits pour apparaître dans les applications du monde réel. – Lykos

0

La réponse proposée est bonne, mais vous devez compter jusqu'à votre logarithme et il y a un peu plus de manière efficace, si vous savez que le logarithme a une limite supérieure, à savoir si vous savez que vous ne traitez avec des nombres supérieurs à 1 < < liés.

def faster_log2(n) 
    l = 0; bound = 64 
    while bound > 0 
    if 1 <<bound> n 
     n >>= bound; l += bound 
    end 
    bound >>= 1 
    end 
    l 
end 

Si vous ne disposez pas d'une limite supérieure, mais vous voulez continuer à utiliser cet algorithme, vous pouvez également calculer une limite avant d'exécuter l'algorithme, mais si les performances ne sont pas un problème, alors je collerait avec la solution plus courte.

def bound(n) 
    bound = 1; 
    bound >>= 1 while 1 << bound < n 
end 
Questions connexes