Je veux trouver si un numéro donné est un Puissance de deux dans une manière mathématique, pas em> avec une approche bitwise. Voici mon code: private static double logBaseTwo(final double x) {
return Math.log(x) / Math.log(2);
}
private static double roundToNearestHundredThousandth(final double x) {
return Math.round(x * 100000.0) / 100000.0;
}
private static boolean isInteger(final double x) {
return (int)(Math.ceil(x)) == (int)(Math.floor(x));
}
public static boolean isPowerOfTwo(final int n) {
return isInteger(roundToNearestHundredThousandth(logBaseTwo(n)));
}
5 Réponses :
C'est vraiment horriblement mauvais code, et je n'ai aucune idée de ce que vous essayez de faire. Vous semblez essayer de vérifier si le journal code> BASE code> 2 code> de n code> est un entier. Au lieu de cela, j'écrirais une boucle:
La solution semble plus compliquée qu'elle ne devrait l'être. Je ne reçois pas les pièces Ceci est la solution simple qui fonctionne pour tous les cas: P> 100000d code> - semble potentiellement causer des problèmes lors de la conversion au plafond. public static boolean isPowerOfTwo(int n) {
return Math.ceil(Math.log(n)/Math.log(2)) == Math.floor(Math.log(n)/Math.log(2));
}
+1. L'arrondi au cent le plus proche est exactement le problème: log₂ 524287 ≈ 18.999997 est arrondi à 19,0, ce qui est un entier. Donc, d'un sens, le code de l'OP arrondi 524287 au 524288, qui est une puissance de deux. (Et, au fait, bienvenue dans le débordement de la pile!)
En fait, désolé, cette réponse n'est pas correcte: ce code renvoie mal false code> pour 536870912 code> (au moins sur mon système), car le résultat du point flottant est 29.000000000000004 code> au lieu de 29 code>.
Les doubles et les flotteurs ont respectivement une précision de 64 bits et 32 bits. Cela signifie qu'ils peuvent contenir au plus grand nombre de Personnellement, les INT sont similaires limités. Ils peuvent contenir jusqu'à 4294967296 numéros différents. Pour INTS, c'est beaucoup plus simple: les intens peuvent tenir à partir de -2147483648 jusqu'à 2147483647. Si vous essayez d'ajouter 1 à 2147483647, vous obtenez -2147483648 (en silence en silence). Il est tout à fait possible que vous rencontrez cela avec une tentative de convertir un nombre aussi grand (votre double fois 10000D) à un int d'abord. P>
Notez que Voir les autres réponses pour des approches plus simples de ce problème. Bien que, bien sûr, la solution la plus simple consiste simplement à compter simplement les bits dans le nombre. Si c'est précisément 1 bit, c'est une puissance de 2. Si c'est 0 bits, eh bien, vous me dites si vous considérez "0" une puissance de 2 :) p> 18446744073709551616 code> numéros uniques. C'est beaucoup de chiffres, mais pas une quantité infinie d'entre eux. À un moment donné (en fait, ce point survient à 2 ^ 52), le «écart» entre tous les 2 chiffres faisant partie des utilisateurs de 18446744073709551616 représentables devient supérieur à 1.000. Des règles similaires s'appliquent aux petits nombres. Math.log utilise-t-il double code> mathématiques basées. P>
? TRUE: FALSE code> (comme dans la version originale de la question) est littéralement complètement inutile. La chose à gauche du point d'interrogation doit être un booléen et les booléens sont déjà vrais ou faux, c'est leur nature. P>
À l'origine, j'ai eu un problème en utilisant Essayez ceci. p> Si vous préférez utiliser des journaux, vous pouvez le faire de cette façon. P> math.log code> dans mes calculs. Je suis passé à math.log10 code> et le problème est parti. Bien que mathématiquement, tout logbe code> de base B devrait fonctionner, la nature des calculs de points flottants peut être imprévisible. public static boolean isPowerOfTwo(int n) {
return n > 0 && (Math.log10(n)/Math.log10(2))%1 == 0;
}
C'était mon erreur et je suis incertain de la façon dont je l'ai négligé. Utiliser Math.Log n'a pas éliminé l'erreur de mathématique, donc je suis passé à Math.Log10 et cela a fonctionné. Cela me dérange toujours parce que l'utilisation du journal code> code> de n'importe quelle base du numérateur et du dénominateur doit fonctionner. Mais c'est des mathématiques et nous travaillons avec IEEE754, de sorte que même l'utilisation du CEIL et des méthodes de plancher n'élimineraient pas la minuscule erreur du calcul.
Votre code échoue car vous aurez peut-être besoin de plus de précision que vous permettant de capturer la différence entre les journaux de Big_Number et Big_Number + 1
Le chemin Bitwise est vraiment meilleur, mais si vous voulez vraiment utiliser uniquement des opérations "mathy" , alors le meilleur que vous puissiez faire est probablement: p> Cette solution ne nécessite aucune précision super-fine et fonctionnera bien pour tous les InTS positifs. P> < / p>
J'espère que vous réalisez que l'utilisation d'une approche mathématique est une approche mathématique. Ils suggèrent que vous suggérez est trop complexe et a du mal à travailler sur des ordinateurs.
@RUAKH Il est faux de modifier la question de sorte qu'il invalide une réponse. S'il vous plaît mettre l'opérateur du TrinGal.
@Nomadmaker: La question concernait pourquoi le code ne fonctionne pas. Comme RzwitserLoot a souligné, l'opérateur ternaire n'a pas affecté le comportement du code; Donc, ce n'est pas vraiment pertinent pour la question.
@ruakh il confond la compréhension de la réponse. Il aurait dû être laissé dans ou un commentaire mis dans la question indiquant que le code d'origine (...) a été remplacé par ce code (...).
@Nomadmaker: J'ai maintenant édité cette réponse pour clarifier ce que cela fait référence.