8
votes

Nombre de zéros dans la représentation binaire d'un entier

Dupliqué possible:
meilleur algorithme de compter le nombre de bits définis dans un entier 32 bits?

Étant donné un entier 32 bits, concevez un algorithme pour trouver le nombre de zéros dans la représentation binaire du bit de n.

L'algorithme le plus simple que je peux penser est de vérifier la représentation binaire des zéros , en C quelque chose comme ceci: xxx

J'étais errant s'il y a un algorithme pour calculer à temps constant.

pour l'entrée 0 < / forte> il devrait retourner 1 non 32 .

pour 5 La sortie doit être de la représentation binaire de 1 Strong> 101 .

pour 7 la sortie doit être 0.

précisément, je cherche un meilleur algorithme pour calculer le nombre de zéros (non-dirigeants) Dans l'interprétation binaire d'un integer 32 bits.Hope, le problème est clair maintenant.

EDIT: AS-MONTRÉ Alex Martelli, Delroth Je modifie mon code pour le rendre plus lisible & en utilisant l'itération cette fois.


11 commentaires

Dupliquer. Voir Stackoverflow.com/Questtions/109023/...


num_of_zero (num >> 1); Si (! (Num & 1)) comptez ++; Pouvez-vous rompre cela? Je ne vois pas comment ça va marcher. Est-ce que je manque quelque chose d'évident?


Je ne suis pas un grand fan de devoir marquant jusqu'à ce que l'OP ait eu la chance de répondre à la requête. Il y a un grand précédent pour les personnes auto-apprenantes. Et, si cela est devoirs et qu'ils utilisent une solution trouvée Verbatim sur le net, ils seront presque certainement échoués pour le plagiat (si leurs éducateurs ont même un modicum d'intelligence).


@nthgeek, si ce est devoirs, merci de l'étiqueter ainsi.


Oh, et je ne crois pas que ce soit techniquement un duplicata - que référence on a demandé à un bits qui est subtilement différent - vous ne pouvez pas utiliser le truc d'arrêt tôt lorsque la valeur est nulle puisque, comme @Alexm souligne dans son excellente réponse. , vous manquez sur les plus grands zéros.


Peut être résolu avec le nombre de hammings parce que num_of_zero (n) == numéros d'analyse (~ n) . Problème équivalent, mais une déclaration légèrement différente de celle-ci.


@paxdiablo: Non, ce n'est pas un problème de travail à la maison, je cherche un meilleur algorithme car c'est O (n).


@ Chrisineinedmonton: Eh bien, Howz, ce problème est en double? !! Je recherche un nombre de bits transparents non-poings non définis.


Eh bien, lorsque cette discussion a commencé, vous n'aviez pas spécifié "non-diriger", ce qui en fait un problème légèrement différent.


Désolé, mais j'ai essayé de modifier le problème que la fois seulement, mais Stackoverflow s'est écrasé.


Hein !! Dupliquer exact? !! Je cherchais un nombre de zéros de premier plan pas de nombre de bits fixes !!


7 Réponses :


6
votes

Le moyen simple de le faire est d'itérer chaque bit de la représentation binaire du nombre, de tester la valeur de chaque bit et de compter le nombre d'entre eux zéro. Une boucle serait beaucoup plus claire que la récursion pour cela.

Il existe de nombreuses méthodes plus optimisées pour le faire, cependant. Vous pouvez trouver certaines des meilleures dans les réponses à cette question, " meilleur algorithme pour compter le nombre de bits définis dans un entier 32 bits " (évidemment, le nombre de bits zéro est le nombre de bits définis soustraits du nombre total des bits).


5 commentaires

Ceci est plus simple et je suis conscient de cela, tout meilleur algorithme? Comme celui que nous avons pour les bits fixes?


Vous pouvez utiliser l'un de ces algorithmes, car la somme du nombre de bits définies et le nombre de bits non définis est le nombre total de bits. Si vous souhaitez connaître le nombre de zéros non-poings, vous pouvez nous permettre le journal-base-2 du numéro pour déterminer l'index du bit de jeu le plus élevé; Il y a des algorithmes pour la trouver aussi rapidement.


Le site Web Twiddling Hacks, qui supprimant les référencesFire de sa réponse, a plusieurs façons de trouver le log-base-2: graphiques.stanford.edu/~Seander/bitacks.html#IntegerLogobvio US


Merci et +1 pour me faire savoir sur la chose de journal-2 chose :). Mais pouvez-vous s'il vous plaît aidez-vous à comprendre comment cela aide-t-il pour réduire la complexité de ce problème?


Le nombre de zéros non-dirigeants dans un INT non signé INT est le même que le nombre de bits définis dans [((2 ^ (LG2 (N)) - 1) et (~ N)].



1
votes

Ce n'est pas vraiment une réponse à votre question principale, mais vous devez réécrire votre fonction récursive comme ceci:

int num_of_zero(int num)
{
    int left_part_zeros;

    if (num == 0)
        return 0;

    left_part_zeros = num_of_zero(num >> 1);
    if ((num & 1) == 0)
        return left_part_zeros + 1;
    else
        return left_part_zeros;
}


0 commentaires

4
votes

manière rapide et muette - il existe des implémentations plus exotiques dans la question en double, mais j'ai utilisé quelque chose de similaire à celui-ci sans beaucoup d'effet malade dans le passé.

Nous utilisons une table de grignotins ici pour réduire le nombre de fois la boucle est exécutée - si vous faites une charge de bateau de ces calculs, il pourrait être plus efficace de construire un tableau beaucoup plus grand, dites, au niveau des octets, couper la boucle de la boucle en deux. P>

/* How many bits are set in every possible nibble. */
static size_t BIT_TABLE[] = {
    0, 1, 1, 2,     /* 0, 1, 2, 3 */
    1, 2, 2, 3,     /* 4, 5, 6, 7 */
    1, 2, 2, 3,     /* 8, 9, A, B */
    2, 3, 3, 4      /* C, D, E, F */
};

size_t num_of_bits(int num) {
    /* Little reworking could probably shrink the stack space in use here. */
    size_t ret = 0, i;
    register int work = num;

    /* Iterate every nibble, rotating the integer in place. */
    for(i = 0; i < (sizeof(num) * 2); i++) {
        /* Pointer math to get a member of the static array. */
        ret += *(BIT_TABLE + (work & 0xF));
        work >>= 4;
    }
    return ret;
}


0 commentaires

2
votes

Récursion est définitivement surkill - et d'ailleurs, votre buggy de votre code (il ne comptera pas l'un des leader zéros de num !!!). Une simple itération, telle que: xxx

est correct et plus rapide (peut être codé plus concis, mais je pense que c'est l'expression la plus claire).

Si vous devez Faites ce calcul à plusieurs reprises, envisagez de préciser un tableau de (dire) 256 "Compte de zéros" (chaque valeur donnant le compte pour son indice de 0 à 255 incluse, en tant que nombre de 8 bits). Ensuite, vous pouvez faire une boucle seulement 4 fois (masquage et déplacement de 8 bits à la fois), et dérouler facilement la boucle - si votre compilateur n'est pas assez intelligent pour le faire en votre nom; -).


6 commentaires

Merci, je ne veux pas compter de zéros de premier plan.


Intéressant Comment vous avez changé et radicalement vos spécifications dans la modification de votre question - ne serait-il pas plus gentil d'exprimer les spécifications droite en premier lieu ?! De plus, si vous ne voulez pas compter N'importe quel Les Zeros de premier plan, comme vous le direz maintenant, comment peut-on le résultat pour 0 1, car vous le prétendez maintenant que cela devrait être dans votre édition récente de votre réponse? Ce zéro que vous voulez compter est "menant". Devinez que vous devriez avoir une observation spéciale d'un étrange aberrant - le seul et unique cas dans lequel vous DO veulent compter un 0 0! -) En dehors de cela, tandis que (UNum) < / code> comme la boucle au lieu de pour & c fonctionnera bien.


Désolé, mais j'ai essayé de modifier la question à cette époque, mais j'avais 503 erreurs à chaque fois !!


Ouais, j'ai eu une longue période de 500 ans. Quoi qu'il en soit, oui, cela finit comme étant propre, nettoyé d'autres absurdités en plus de la récursion, telle que celle statique .


Je suis étranger, mon commentaire a disparu? !! Mais sûrement merci :)


Comme indiqué par vous et un autre, j'avais modifié mon code, j'espère qu'il n'y a pas de problème maintenant :-)



5
votes

Il y a une excellente ressource en ligne appelée BIT TwidDling Hacks contenant toutes sortes de Superbes petites tours. Vous pouvez être particulièrement intéressé par le Comptage des bits Set section.


0 commentaires

2
votes

Je suppose que c'est une question de devoirs. Aucun problème! Voici la solution la plus rapide possible (après un coût de démarrage long):

Créez un tableau de octet qui est 2 32 long. Précalcompute la valeur du nombre de zéros dans la représentation binaire pour chaque valeur possible int pour remplir ce tableau. À partir de ce moment, vous aurez une matrice qui vous donnera le nombre de zéros par valeur.

Oui, cette solution est stupide - c'est beaucoup de travail pour peu de gain - mais le combine avec une autre idée:

Que se passe-t-il si vous précalisez simplement les valeurs de 8 bits longs? Seriez-vous capable d'écrire du code qui, mais pas tout à fait aussi rapide, retournerait toujours le nombre de 0-bits dans un int?

Que se passe-t-il si vous venez de précomputer les valeurs de 4 bits longs? 2 bits longs? 1 bit de long?

J'espère que cela vous donne des idées pour un meilleur algorthme ...


3 commentaires

Crikey, un tableau de 4 milliards d'octets. J'étais sur le point de savoir cela jusqu'à ce que je voyais où vous alliez :-)


J'ai écrit ce commentaire lorsque la question est sortie de la première fois. Stackoverflow s'est écrasé avant que je le soumise. Quand je suis rentré, d'autres avaient répondu à la question. Je voulais que ma réponse se présente toujours. Et, ouais, paxdiablo - la réponse originale est stupide. Mais j'avais espéré que cela donnerait de meilleures idées.


Peut-être que tellement écrasé parce qu'il a manqué de mémoire essayant de calculer la table de recherche à 4 gigues ... :-) Quoi qu'il en soit, je pensais que c'était une bonne réponse (+1).



1
votes

La voie la plus simple que j'ai trouvée était de le baser sur quelque chose qui compte ceux qui comptent alors soustrayez simplement que de 32 (en supposant que vous êtes sûr em> la taille int code> est de 32 BITS).

int numberOfOnes (int num) {
    static const count[] = {
        0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
    };
    int retval = 0;
    unsigned int u = (unsigned int)num;
    while (u != 0) {
        retval += count[u & 0x0f]
        u >>= 4;
    }
    return retval;
}


1 commentaires

Si c'est ce que je cherche, je voudrais mieux utiliser alors que (Num) {Nombre ++; Num & = (num - 1)} pour calculer le nombre de bits de jeu.