2
votes

Fonction de conversion binaire

J'essaye de convertir une valeur décimale en binaire en utilisant la fonction que j'ai écrite en C ci-dessous. Je ne peux pas comprendre la raison pour laquelle il affiche 32 zéros plutôt que la valeur binaire de 2.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>

int binaryConversion(int num){
    int bin_buffer[32];
    int mask = INT_MIN;
    for(int i = 0; i < 32; i++){
        if(num & mask){
            bin_buffer[i] = 1;
            mask >> 1;
        }
        else{
            bin_buffer[i] = 0;
            mask >> 1;
        }
    }
    for(int j = 0; j < 32; j++){
        printf("%d", bin_buffer[j]);
    }
}


int main(){
    binaryConversion(2);
}

Merci


0 commentaires

4 Réponses :


3
votes

Deux erreurs:

  1. Vous utilisez >> au lieu de >> = , vous ne changez donc jamais jamais le masque .
  2. Vous n'avez pas déclaré le masque comme non signé , donc lorsque vous changez de vitesse, il sera étendu par signe, ce que vous ne voulez pas.

3 commentaires

Oui, c'est à peu près tout. Autant déplacer mask >> = 1; en dehors du bloc if car il sera exécuté malgré tout.


Erreur n ° 3: INT_MIN peut avoir plus d'un bit défini. Les valeurs communes pour INT_MIN n'ont qu'un seul bit défini, mais la plus petite valeur de magnitude pour INT_MIN est 32767.


@ 1201ProgramAlarm: oui, c'est possible, mais cela a tendance à être sur des environnements qui ont un codage complémentaire ou de magnitude de signe pour les nombres négatifs, qui sont rares. C ++ a déjà choisi d'insister sur le complément à deux dans C ++ 20 et ISO C envisage le même mouvement. J'espère que nous serons débarrassés de ces encodages bizarres à un moment donné :-)



2
votes

Si vous mettez un:

int binaryConversion(unsigned int num) {
    // Done once to set topBit.

    static unsigned topBit = 0;
    if (topBit == 0) {
        topBit = 1;
        while (topBit << 1 != 0) topBit <<= 1;
    }

    // Loop to process all bits.

    for (unsigned mask = topBit; mask != 0; mask >>= 1)
        putchar(num & mask ? '1' : '0');
}

immédiatement dans votre boucle for , vous verrez pourquoi:

#include <stdio.h>
#include <limits.h>

int binaryConversion(unsigned num) {
    for (unsigned mask = (unsigned)INT_MIN; mask != 0; mask >>= 1)
        putchar((num & mask) ? '1' : '0');
}

int main(void) {
    binaryConversion(2);
    putchar('\n');
}

L'expression mask >> 1 décale vers la droite la valeur du mask mais ne l'attribue pas en fait au mask . Je pense que vous vouliez utiliser:

mask >>= 1;

En plus de cela (une fois que vous aurez résolu ce problème), vous verrez que le les valeurs dans le masque sont un peu étranges car déplacer une valeur négative vers la droite peut préserver le signe, ce qui signifie que vous vous retrouverez avec plusieurs bits définis.

Vous feriez mieux utiliser des entiers non signés car l'opérateur >> agira sur eux plus en ligne avec vos attentes.


De plus, il est inutile d'écrire tous ces bits dans un tampon juste afin que vous puissiez les imprimer plus tard. À moins que vous n'ayez besoin de manipuler les bits (et cela ne semble pas être le cas ici), vous pouvez simplement les afficher directement au fur et à mesure qu'ils sont calculés (et vous débarrasser de la variable i désormais inutile. ).


Donc, en tenant compte de tous ces points, vous pouvez grandement simplifier votre code comme avec le programme complet suivant:

2 -2147483648
2 -2147483648
2 -2147483648
2 -2147483648
:
2 -2147483648

Et juste une dernière remarque, la valeur de INT_MIN n'est pas réellement nécessaire pour avoir juste le bit supérieur défini. En raison de la tolérance actuelle de C pour gérer le complément à un et l'amplitude du signe (ainsi que le complément à deux) pour les nombres négatifs, il est possible pour INT_MIN d'avoir une valeur avec plusieurs bits définis (comme -32767 code >).

Il y a des démarches en cours pour supprimer ces encodages peu utilisés de C (C ++ 20 l'a déjà signalé) mais, pour une portabilité maximale, vous pouvez opter pour la fonction suivante: p>

printf("%d %d\n", num, mask);

Ceci calcule la valeur avec le bit supérieur défini la première fois que vous appelez la fonction, indépendamment des caprices des encodages négatifs. Faites juste attention si vous l'appelez simultanément dans un programme threadé.

Mais, comme mentionné, ce n'est probablement pas nécessaire, le nombre d'environnements qui utilisent les deux autres encodages serait comptable sur les doigts d'un opérateur de machine industrielle très imprudent / malchanceux.


0 commentaires

0
votes

Vous avez déjà répondu à votre question principale concernant l'utilisation de >> plutôt que de =>> . Cependant, d'un point de vue fondamental, il n'est pas nécessaire de mettre en mémoire tampon le 1 et le 0 dans un tableau de int (par exemple int bin_buffer [ 32]; ) et il n'est pas nécessaire d'utiliser la fonction variadic printf pour afficher les valeurs int si tout ce que vous faites est afficher la représentation binaire du nombre.

Au lieu de cela, il vous suffit de putchar () pour afficher '1' ou '0' selon que n'importe quel bit est activé ou désactivé. Vous pouvez également rendre votre fonction de sortie un peu plus utile en fournissant la taille de la représentation souhaitée, par exemple un octet (8 bits), un mot (16 bits), et ainsi de suite.

Par exemple, vous pouvez faire: p>

$ ./bin/binaryconversion
byte : 00000010
word : 0000000000000010

Ce qui vous permet de définir le nombre de bits que vous souhaitez afficher, par exemple

Exemple d'utilisation / de sortie

XXX

Il n'y a rien de mal avec votre approche, mais il peut y avoir un moyen plus simple d'arriver au même résultat.

Faites-moi savoir si vous avez d'autres questions. p>


0 commentaires

0
votes

INT_MIN est un nombre négatif donc lorsque vous vous déplacez vers la droite en utilisant >> , le bit le plus significatif sera toujours 1 au lieu de zéro et vous vous retrouverez dans mask = 11111 ... 111 tous les bits ont la valeur 1 . De plus, la valeur du mask ne change pas. mieux vaut utiliser >> = à la place. Vous pouvez essayer de masquer sur 0x1 et décaler la valeur réelle de num au lieu du masque comme ceci.

int binaryConversion(int num) {
    char bin_buffer[32 + 1];  //+1 for string terminator.
    int shifted = num;
    for (int i = 31; i >= 0; --i, shifted >>= 1) {  //loop 32x
        bin_buffer[i] = '0' + (shifted & 0x1);
    }
    bin_buffer[32] = 0;  //terminate the string.

    printf("%s", bin_buffer);

}


0 commentaires