109 votes

Calculer des puissances d'entiers

Existe-t-il un autre moyen en Java de calculer une puissance d'un nombre entier ?

J'utilise Math.pow(a, b) maintenant, mais il renvoie un double et c'est généralement beaucoup de travail, et cela semble moins propre quand on veut simplement utiliser int (un pouvoir aura donc aussi toujours pour résultat un int ).

Y a-t-il quelque chose d'aussi simple que a**b comme en Python ?

2 votes

Il s'agit peut-être d'un double de cette question. stackoverflow.com/questions/101439/

71voto

Stachu Barański Points 139

Quand il s'agit d'une puissance de 2. Gardez à l'esprit que vous pouvez utiliser une expression de décalage simple et rapide. 1 << exponent

exemple :

2 2 \= 1 << 2 = (int) Math.pow(2, 2)
2 10 \= 1 << 10 = (int) Math.pow(2, 10)

Pour les exposants plus grands (plus de 31), utilisez la méthode longue.

2 32 \= 1L << 32 = (long) Math.pow(2, 32)

Au fait, en Kotlin, vous avez shl au lieu de << donc

(java) 1L << 32 = 1L shl 32 (kotlin)

63voto

JB Nizet Points 250258

Les nombres entiers ne comportent que 32 bits. Cela signifie que sa valeur maximale est 2^31 -1 . Comme vous le voyez, pour les très petits nombres, vous avez rapidement un résultat qui ne peut plus être représenté par un entier. C'est pourquoi Math.pow utilise double .

Si vous voulez une précision arbitraire des entiers, utilisez BigInteger.pow . Mais c'est bien sûr moins efficace.

77 votes

+1, c'est vrai. Mais je trouverais bien que le Java les architectes ont ajouté pow(int, int) . Tu sais, parfois tu veux juste que 5^6 et ne se soucient pas du tout des doubles.

6 votes

Je ne fais que supposer, mais je pense qu'ils ne l'ont pas fait parce qu'une telle méthode conduirait à des résultats complètement incorrects dans la plupart des cas. Principe du moindre étonnement.

4 votes

Oui, c'est un bon point. Mais quand vous êtes un ignorant et que vous travaillez avec int rien ne vous empêche de vous convertir en (int) une valeur débordante.

43voto

Laakal Points 535

Le meilleur algorithme est basé sur la définition récursive de la puissance de a^b.

long pow (long a, int b)
{
    if ( b == 0)        return 1;
    if ( b == 1)        return a;
    if (isEven( b ))    return     pow ( a * a, b/2); //even a=(a^2)^b/2
    else                return a * pow ( a * a, b/2); //odd  a=a*(a^2)^b/2

}

Le temps d'exécution de l'opération est O(logb). Référence : Plus d'informations

3 votes

Et qu'est-ce que isEven(b) fait-elle ? Est-ce la même chose que b % 2 == 0 ?

2 votes

Je me demande aussi... Ce type est parti et nous laisse dans l'expectative ... Des programmeurs maladroits ...

0 votes

Inexistant (isEven(b))' function -- meaning ((b & 1) == 0)` -- et un algorithme compliqué inutile ! (

38voto

Petar Minchev Points 24864

Non, il n'y a pas quelque chose d'aussi court que a**b

Voici une boucle simple, si vous voulez éviter les doubles :

long result = 1;
for (int i = 1; i <= b; i++) {
   result *= a;
}

Si vous voulez utiliser pow et convertir le résultat en un nombre entier, en convertissant le résultat comme suit :

int result = (int)Math.pow(a, b);

5 votes

@DmitryGinzburg : étant donné un long est de 64 bits, alors O(n) a 64 comme limite supérieure. Est-ce vraiment si grave ?

1 votes

@Thomas non, vous avez tort ; si b es 2_000_000_000 alors vous devrez faire 2e9 au lieu de 31 en autre solution

2 votes

@DmitryGinzburg : vous aurez beaucoup de problèmes de débordement dans ce cas. Le code de l'OP n'inclut pas la validation des arguments. Le nombre maximum autorisé devrait être 64 dans le cas où a est aussi petit que 2 (et pour a=1, cela n'a pas de sens).

9voto

ant Points 131

Google Guava dispose d'utilitaires mathématiques pour les nombres entiers. IntMath

Prograide.com

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.

Powered by:

X