Étant donné 2 ^ n, trouver n en utilisant le logarithme

Étant donné un entier (2 ^ n) qui est la puissance de 2, je veux trouver n, la valeur d’index en utilisant le logarithme. La formule pour trouver l’index est la suivante: log (numéro) / log (2). Voici l’extrait de code:

unsigned long int a; double apower; apower = log((double)a) / log((double)2); 

J’ai trouvé que la valeur de ‘apower’ est fausse avec une valeur élevée de a, je ne connais pas la valeur, car mon code échoue, après l’avoir envoyé. Pourquoi est-ce? Y a-t-il un problème de casting?

Voici l’extrait complet:

  int count = 0; unsigned long int a,b; double apower,bpower; apower = log((double)a) / log((double)2); bpower = log((double)b) / log((double)2); count = abs(apower - bpower); printf("%d\n",count); 

Les valeurs de a et b seront toujours égales à la puissance 2. Ainsi, apower et bpower doivent avoir 00 en décimales. C’est pourquoi la valeur du compte sera int (% d). Je veux juste connaître le comportement de Logarithm.

Lorsque vous utilisez un double calcul, le résultat ou le quotient du journal peut ne pas être exactement le résultat mathématique, mais 1 (ou 2) immédiatement représentable du double .

Le calcul de log() ne renvoie qu’un résultat mathématique exact pour log(0) , tous les autres résultats mathématiques sont irrationnels. Tous les double sont rationnels.

Cela peut entraîner une réponse du type 29.999999 …, enregistrée sous la forme d’un entier égal à 29.

Recommander l’utilisation de maths entier à la place


 int mylog2(unsigned long x) { int y = 0; #if (ULONG_MAX>>16 > 1lu<<16) if (x >= 1lu<<32) { x >>= 32; y += 32; #endif if (x >= 1lu<<16) { x >>= 16; y += 16; } if (x >= 1lu<<8) { x >>= 8; y += 8; } if (x >= 1lu<<4) { x >>= 4; y += 4; } if (x >= 1lu<<2) { x >>= 2; y += 2; } if (x >= 1lu<<1) { x >>= 1; y += 1; } return y; } 

Je ne réponds qu’à la moitié de votre question, car il n’est pas nécessaire d’utiliser des journaux pour résoudre ce problème. Un moyen simple consiste à utiliser ceci:

 unsigned long long a = 0x8000000000000000ULL; int n = 0; while (a >>= 1) n++; printf("%d\n", n); 

Sortie:

 63 

La conversion en journaux et la division peuvent entraîner une perte de signification, auquel cas vous devriez utiliser round . Vous utilisez le mot “soumettre”, donc c’était un défi en ligne qui a échoué? Qu’as-tu imprimé exactement? (dans ce cas) 63.000000 ? Cela serait obtenu à partir du format par défaut de %f .

Pourquoi ne pas tirer parti du fait que le log2 est stocké dans le champ exposant d’un double? 🙂

 unsigned long long a = 0x8000000000000000ULL; union { double d; unsigned long long l; } u; ud = a; int apower = (ul >> 52) - 1023; printf("%d\n", apower); 

Sortie:

 63 

Cela suppose que les doubles longs et non signés sont en 64 bits et que l’entrée est> 0.