Calcul de la nième racine en Java à l'aide de la méthode power


J'essayais d'obtenir une racine cubique en java en utilisant Math.pow(n, 1.0/3) mais parce qu'elle divise les doubles, elle ne renvoie pas la réponse exacte. Par exemple, avec 125, cela donne 4.9999999999. Est-il une solution pour cela? Je sais qu'il existe une fonction racine cubique, mais j'aimerais résoudre ce problème afin de pouvoir calculer des racines plus élevées.

Je ne voudrais pas arrondir parce que je veux savoir si un nombre a une racine entière en faisant quelque chose comme ceci: Math.pow(n, 1.0 / 3) % ((int) Math.pow(n, 1.0 / 3)).

Author: Tunaki, 2015-09-13

7 answers

Le Mathématiques.la fonction round arrondit à la valeur longue la plus proche qui peut être stockée sur un double. Vous pouvez comparer les 2 résultats pour voir si le nombre a une racine cubique entière.

double dres = Math.pow(125, 1.0 / 3.0);
double ires = Math.round(dres);
double diff = Math.abs(dres - ires);
if (diff < Math.ulp(10.0)) {
    // has cubic root
}

Si cela est insuffisant, vous pouvez essayer d'implémenter cet algorithme et arrêter tôt si le résultat ne semble pas être un entier.

 5
Author: Manos Nikolaidis, 2015-09-13 18:53:54

Comme il n'est pas possible d'avoir un calcul de précision arbitraire avec double , vous avez trois choix:

  1. Définissez une précision pour laquelle vous décidez si une valeur double est un entier ou non.
  2. Testez si la valeur arrondie du double que vous avez est un résultat correct.
  3. Faire le calcul sur un BigDecimal objet, qui prend en charge les valeurs doubles de précision arbitraire.

Option 1

private static boolean isNthRoot(int value, int n, double precision) {
    double a = Math.pow(value, 1.0 / n);
    return Math.abs(a - Math.round(a)) < precision; // if a and round(a) are "close enough" then we're good
}

Le problème avec cette approche est de savoir comment définir "assez près". C'est une question subjective et dépend de vos besoins.

Option 2

private static boolean isNthRoot(int value, int n) {
    double a = Math.pow(value, 1.0 / n);
    return Math.pow(Math.round(a), n) == value;
}

L'avantage de cette méthode est qu'il n'est pas nécessaire de définir une précision. Cependant, nous devons effectuer une autre opération pow, ce qui affectera les performances.

Option 3

Il n'y a pas de méthode intégrée pour calculer une double puissance d'un BigDecimal. Cette question vous donnera un aperçu sur la façon de le faire.

 5
Author: Tunaki, 2017-05-23 10:29:47

J'irais pour implémenter ma propre fonction pour le faire, éventuellement basé sur cette méthode.

 1
Author: dimplex, 2015-09-13 18:57:50

J'ai écrit cette méthode pour calculer floor(x^(1/n))x est un BigInteger non négatif et n est un entier positif. C'était il y a un certain temps maintenant, donc je ne peux pas expliquer pourquoi cela fonctionne, mais je suis raisonnablement confiant que lorsque je l'ai écrit, j'étais heureux qu'il soit garanti de donner la bonne réponse raisonnablement rapidement.

Pour voir si x est une exacte n-th puissance, vous pouvez vérifier si le résultat à la puissance n vous donne exactement x retour.

public static BigInteger floorOfNthRoot(BigInteger x, int n) {
    int sign = x.signum();
    if (n <= 0 || (sign < 0))
        throw new IllegalArgumentException();
    if (sign == 0)
        return BigInteger.ZERO;
    if (n == 1)
        return x;
    BigInteger a;
    BigInteger bigN = BigInteger.valueOf(n);
    BigInteger bigNMinusOne = BigInteger.valueOf(n - 1);
    BigInteger b = BigInteger.ZERO.setBit(1 + x.bitLength() / n);
    do {
        a = b;
        b = a.multiply(bigNMinusOne).add(x.divide(a.pow(n - 1))).divide(bigN);
    } while (b.compareTo(a) == -1);
    return a;
}

Pour utiliser il:

System.out.println(floorOfNthRoot(new BigInteger("125"), 3));

Modifier Après avoir lu les commentaires ci-dessus, je me souviens maintenant que c'est la méthode de Newton-Raphson pour les n-roots racines. La méthode de Newton-Raphson a une convergence quadratique (ce qui signifie dans le langage courant qu'elle est rapide). Vous pouvez l'essayer sur les nombres qui ont des dizaines de chiffres et vous devriez obtenir la réponse en une fraction de seconde.

Vous pouvez adapter la méthode pour fonctionner avec d'autres types de nombres, mais double et BigDecimal ne sont à mon avis pas adaptés à ce type de chose.

 1
Author: Paul Boddington, 2015-09-13 19:57:58

Eh bien, c'est une bonne option à choisir dans cette situation. Vous pouvez compter sur cela -

   System.out.println("     ");
   System.out.println("     Enter a base and then nth root");
   while(true)
   {
       a=Double.parseDouble(br.readLine());
       b=Double.parseDouble(br.readLine());
       double negodd=-(Math.pow((Math.abs(a)),(1.0/b)));
       double poseve=Math.pow(a,(1.0/b));
       double posodd=Math.pow(a,(1.0/b));
       if(a<0 && b%2==0)
       {
           String io="\u03AF";
           double negeve=Math.pow((Math.abs(a)),(1.0/b));
           System.out.println("     Root is imaginary and value= "+negeve+" "+io);
       }
       else if(a<0 && b%2==1)
       System.out.println("     Value= "+negodd);
       else if(a>0 && b%2==0)
       System.out.println("     Value= "+poseve);
       else if(a>0 && b%2==1)
       System.out.println("     Value= "+posodd);
       System.out.println("     ");
       System.out.print("     Enter '0' to come back or press any number to continue- ");
       con=Integer.parseInt(br.readLine());
       if(con==0)
       break;
       else
       {
           System.out.println("     Enter a base and then nth root");
           continue;
       }
    }
 0
Author: Avneesh Singh, 2016-03-28 12:08:25

C'est un hack assez laid, mais vous pourriez en atteindre quelques-uns par indentation.

System.out.println(Math.sqrt(Math.sqrt(256)));
    System.out.println(Math.pow(4, 4));
    System.out.println(Math.pow(4, 9));
    System.out.println(Math.cbrt(Math.cbrt(262144)));
Result:
4.0
256.0
262144.0 
4.0

Qui vous donnera chaque n^3ème cube et chaque n^2ème racine.

 0
Author: Sam, 2017-12-04 20:22:17

Vous pouvez utiliser quelques astuces provenant du domaine des mathématiques, pour avoirplus de précision. Comme celui-ci x^(1/n) = e^(lnx/n).

Vérifiez l'implémentation ici: https://www.baeldung.com/java-nth-root

 0
Author: Grigoris Dimopoulos, 2018-10-06 11:39:17