web-dev-qa-db-fra.com

Comment les lettres majuscules et minuscules diffèrent-elles d'un seul bit?

J'ai trouvé un exemple dans le livre Data and Communication Networking écrit par Behrouza Forouzan concernant les lettres majuscules et minuscules qui ne diffèrent que d'un bit dans le code à 7 bits.

Par exemple, le caractère A est 1000001 (0x41) et le caractère a est 1100001 (0x61). La différence est exprimée en bit 6, qui correspond à 0 en majuscule et à 1 en minuscule. Si nous connaissons le code pour un cas, nous pouvons facilement trouver le code pour l'autre en ajoutant ou en soustrayant 32 en décimal, ou nous pouvons simplement inverser le sixième bit.

Qu'est-ce que tout cela signifie?

Je me suis trouvé très confus avec toutes ces choses. Quelqu'un pourrait-il donner des exemples de la manière dont ces choses fonctionnent vraiment?

13
Vibhakar SInha

Utilisons un cas que vous trouverez plus familier: la base 10.

  1. Supposons que nous ayons un ordinateur de base 10, dans lequel chaque 10 bits stocke une valeur de 0 à 9, et un octet a une longueur de 5 à 10 bits, de sorte que chaque octet peut stocker 100 000 valeurs (0 à 99 999).

  2. Vous souhaitez attribuer des lettres à des positions particulières dans un octet afin que cet ordinateur puisse communiquer des données texte avec d'autres ordinateurs. Une façon de faire serait la suivante:

    00101 A    00201 a
    00102 B    00202 b
    00103 C    00203 c
    00104 D    00204 d
    00105 E    00205 e
    00106 F    00206 f
    00107 G    00207 g
    00108 H    00208 h
    00109 I    00209 i
    00110 J    00210 j
    00111 K    00211 k
    00112 L    00212 l
    00113 M    00213 m
    00114 N    00214 n
    00115 O    00215 o
    00116 P    00216 p
    00117 Q    00217 q
    00118 R    00218 r
    00119 S    00219 s
    00120 T    00220 t
    00121 U    00221 u
    00122 V    00222 v
    00123 W    00223 w
    00124 X    00224 x
    00125 Y    00225 y
    00126 Z    00226 z
    
  3. Voyez-vous que chaque lettre minuscule diffère de la lettre majuscule par un seul chiffre à 10 bits, dans la 3ème colonne à partir de la droite? Il n'a pasêtre conçu de cette façon. C’était simplement pratique, car chaque fois que nous voulons ajuster le cas d’une lettre, nous pouvons simplement modifier l’un des chiffres (10 bits) sans nous soucier du reste du numéro ou sans nous soucier de vingt-six transformations différentes lorsque nous pouvons le faire. un . Nous n'aurions pas pu choisir le deuxième chiffre car au lieu d'être séparés de 100, ils ne seraient que 10 et se chevaucheraient.

  4. Maintenant, en base 2, c'est exactement la même chose, mais au lieu de chaque bit représentant 0-9, il ne peut représenter que 0-1. L'utilisation de huit bits 2 bits ne nous donne que 256 combinaisons possibles, 0-255. Les codes ASCII des lettres majuscules et minuscules en binaire ressemblent à ceci:

    01000001 A        01100001 a
    01000010 B        01100010 b
    01000011 C        01100011 c
    01000100 D        01100100 d
    01000101 E        01100101 e
    01000110 F        01100110 f
    01000111 G        01100111 g
    01001000 H        01101000 h
    01001001 I        01101001 i
    01001010 J        01101010 j
    01001011 K        01101011 k
    01001100 L        01101100 l
    01001101 M        01101101 m
    01001110 N        01101110 n
    01001111 O        01101111 o
    01010000 P        01110000 p
    01010001 Q        01110001 q
    01010010 R        01110010 r
    01010011 S        01110011 s
    01010100 T        01110100 t
    01010101 U        01110101 u
    01010110 V        01110110 v
    01010111 W        01110111 w
    01011000 X        01111000 x
    01011001 Y        01111001 y
    01011010 Z        01111010 z
    

    Comme avant, ils ne diffèrent que par un chiffre de 2 bits, ici dans la 6ème colonne à partir de la droite. Nous n'aurions pas pu utiliser un chiffre plus à droite (plus petit) car les listes se seraient superposées (2 ^ 5 = 32 et, par conséquent, nous avons utilisé tous les bits de 0 à 5, mais 2 ^ 4 = 16, ce qui ne pouvait pas couvrir. les 26 lettres de l'alphabet).

  5. Juste pour compléter un peu, voici un exemple de ce que signifient ces valeurs binaires. Prenons celui de G. Pour comprendre ce que 01000111 signifie en binaire:

     Pos:   7  6  5  4  3  2  1  0
     Bit:   0  1  0  0  0  1  1  1
     Val: 128 64 32 16  8  4  2  1
    Mult:   0 64  0  0  0  4  2  1
     Add: 64 + 4 + 2 + 1 = 71, which is the ASCII code for G.
    

    Faites la même chose pour la lettre G dans le système de base spécial 10 que j'ai construit ci-dessus:

      Pos:     4    3    2    1    0
    10Bit:     0    0    1    0    7
      Val: 10000 1000  100   10    1
     Mult:     0    0  100    0    7
      Add: 100 + 7 = 107, which is my special 10ASCII code for G.
    

    Regardez la ligne "Val" pour le binaire. Voyez-vous que, à partir de la droite, chaque valeur est le double de la précédente? Doubler à chaque fois que nous obtenons 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, etc. C’est ainsi que la position d’un chiffre binaire détermine sa valeur, tout comme la position d’un chiffre décimal détermine sa valeur avec des puissances de 10: 1, 10, 100, 1000, 10000, 100000, etc.

    Je me rends compte que cela semble idiot car tout ce que j'ai fait est de convertir 107 en 107 ... mais 107 n'est pas simplement un nombre, il s'agit d'un abrégé pour:

    1 hundreds + 0 tens + 7 ones.
    

    Une autre façon de représenter cela est

    0 x 10^4 + 0 x 10^3 + 1 x 10^2 + 0 x 10^1 + 7 x 10^0.
    

    De même, 01000111 n'est pas simplement un nombre binaire, c'est une forme abrégée pour

    0 x 2^7 + 1 x 2^6 + 0 x 2^5 + 0 x 2^4 + 0 x 2^3 + 1 x 2^2 + 1 x 2^1 + 1 x 2^0
    

    C'est ce que je vous ai déjà montré:

    0 + 64 + 0 + 0 + 0 + 4 + 2 + 1
    = 64 + 4 + 2 + 1
    = 71
    

En outre, vous vous demandez peut-être ce que signifient 0x41 et 0x61. La partie 0x indique que les chiffres à suivre doivent être compris comme hexadécimaux, ce qui correspond à la base 16. Il n’ya que 10 chiffres dans notre système de numérotation, nous avons donc besoin de 6 chiffres supplémentaires. Ainsi, hexadécimal utilise les chiffres 0 à 9 et traite les lettres AF comme les chiffres restants, où A va de 10 à F comme 15. Hexadécimal est très pratique pour les ordinateurs car 16 est une puissance de 2 et un octet de 8 bits prend exactement deux chiffres hexadécimaux à encoder (et chaque chiffre hexadécimal code exactement quatre chiffres binaires). En prenant 0x41, en développant 4 en sa représentation binaire 0100 et en développant 1 en sa représentation binaire 0001, vous obtenez 01000001, qui est le code pour A comme indiqué. Pour le convertir en nombre décimal, il faut 4 x 16 + 1 x 1 = 65. Nous multiplions le nombre 4 par 16 car chaque chiffre hexadécimal successif à gauche correspond à 16 fois le chiffre précédent, suivant le même schéma que celui que je vous ai montré plus haut pour les bases 2 et 10. .

J'espère que cela vous suffit pour en savoir un peu plus sur les codes binaires et ASCII.

Note 1: La raison de 8 bits dans un octet au lieu de 2, comme vous pouvez le penser, c’est que, dans les premiers jours de l’informatique, il a été décidé que 8 est un nombre de bits beaucoup plus utile, Un "octet" sur 2 bits ne coderait que 4 valeurs. Pour transmettre uniquement les lettres majuscules et minuscules de l'alphabet, il vous faudrait 3 octets! Il n’existe rien d’inhérent au binaire qui oblige à choisir 8 bits par octet, si ce n’est que 8 est aussi une puissance de 2, ce qui simplifie énormément les opérations de calcul avec les informations binaires et permet de mieux aligner les contours sur les bords. S'ils avaient choisi 6 bits par octet, je suis sûr que tout se serait bien passé et que toutes les valeurs disponibles n'auraient pas été utilisées.

Note 2: Mon système de cinq bits sur 10 octets repose sur le caractère peu pratique de l’utilisation de dix bits 10 octets par octet, ce qui donne un très grand nombre qui gaspille beaucoup d’espace de stockage. J'ai choisi cinq parce que dix est divisible par elle, ce qui serait sans aucun doute utile. (À l'origine, ma réponse utilisait dix 10 bits par 10 octets, mais elle était trop grosse!)

35
ErikE

Cette relation entre les majuscules et les minuscules était délibérée. Lorsque le code ASCII a été formulé, le matériel informatique était primitif et le logiciel nécessaire pour conserver chaque octet. Inverser un bit nécessite très peu de matériel ou de code.

3
Mark Ransom

http://asciitable.com/

0x61 is hexadecimal for 97 = a
0x41 is hexadecimal for 65 = A

Donc, soustraire/ajouter le nombre décimal 32 est en effet le moyen de convertir en majuscules/minuscules.

Z is 90 = 0b1111010    = 0x5A
z is 122 = 0b1011010   = 0x7A

Ce qui est une différence de 0b01000000 en binaire ou 0x20 ou 32 en décimal.

Ainsi, la commutation du 6ème bit change la casse.

1
Gazler

Je pense que la plupart de ces réponses sont inutilement compliquées et parfois condescendantes. 

Le mappage de caractère décimal à caractère ascii est arbitraire et n’a vraiment rien à voir avec le fonctionnement de la base 2 ou de la base 10. C'est purement une affaire de commodité. Si quelqu'un a codé à tort un caractère minuscule, mais en majuscule, il est plus pratique de retourner un bit au lieu de devoir recoder un octet entier. Il est moins sujet à l'erreur humaine que de retourner un bit. SI la sortie est "a" mais que nous voulions "A", au moins nous savons que nous avons obtenu le meilleur résultat et nous devons simplement retourner 2 ^ 5 pour en ajouter ou en soustraire 32. C'est aussi simple que cela. Pourquoi choisir spécifiquement le bit 5 (ce n’est pas le 6, comme certains l’ont dit, vous commencez à 0 ..), c’est bien celui qui a du sens pour satisfaire deux plages de 26 caractères avec un seul retournement. Si vous faites cela sur un bit de moindre valeur, vous devrez en inverser plus d'un. 

1
shake

Pour additionner ou soustraire 32, vous devez d’abord savoir si le caractère est supérieur ou inférieur à «A».

Lors de la rédaction de ce livre, les langages de programmation que la plupart des gens utilisaient ne comportaient pas de chaînes, ni de .equalsIgnoreCase. C'était pré-i18n, et quand une entreprise avait un serveur, vous lui connectiez telnet (comme xterm) et obteniez un menu en ligne de commande. Ce qu’il décrit est généralement utilisé pour créer un menu de Nice respectant la casse pour les utilisateurs, en tirant parti de la présentation numérique de la table ascii. 

Cela peut être très rapide, car il existe des instructions d'assembleur au niveau des bits permettant d'effectuer le calcul dans les deux sens, que les caractères soient déjà en majuscule ou en minuscule.

c = c | 32 // en majuscule

c = c & (1 + 2 + 4 + 8 + 16 + 0 + 64 + 128) // en minuscule

Supposons que vous utilisiez un langage de type Java, sans objets ni bibliothèques standards. Votre auteur réseau vous invite à coder comme ceci:

    public static void main()
    {
        println("What would you like to do?");
        println("Inventory (inv)");
        println("Reports (rep)");

        char[] ca = readUserInput();        
        for (int i = 0; i < ca.length; i++)
            ca[i] = ca[i] | 32;  // convert to uppercase, by ensuring bit 32 is set

        if (compareInput(ca, "INV") == true)
            doInventory();
    }

Avez-vous essayé de chercher sur Google et parfois mis en majuscule le nom d'une personne?

1
Brian Maltzan

jetez un oeil, le 6ème bit = 32, donc si vous le retournez vous sous-activez ou ajoutez 32

Bit value
1   1
2   2
3   4
4   8
5   16
6   32 (32 = hex 20)

Maintenant, si vous regardez ici http://asciitable.com/ , vous pouvez voir la table ascii pour tous les caractères et remarquerez que A = 65 et a = 97

1
SQLMenace
template<char TLBound, char TUBound>
struct CharRange
{
    enum 
    {
        LBound = TLBound,
        UBound = TUBound
    };

    static bool InRange(char ch)
    {
        return (ch >= LBound)  && (ch <= UBound);
    };
};

typedef CharRange<'a', 'z'> lcaseLetters;
typedef CharRange<'A', 'Z'> ucaseLetters;

char toUpper(char ch)
{
    if(lcaseLetters::InRange(ch))
    {
        return (ch ^ (0x1 << 5));
    }

    return ch;
}

char toLower(char ch)
{
    if(ucaseLetters::InRange(ch))
    {
        return (ch ^ (0x1 << 5));
    }

    return ch;
}
0
Nitheesh George