Je veux dire que vous pouvez comprendre cela vous-même.
Sotirios Delimanolis
30
Oui. J'avoue ... je pêche des chapeaux :)
Bohème
6
Je pense avoir déjà vu cette question posée ici ..
Zavior
6
@Oli Il devrait y avoir un chapeau pour ça.
Sotirios Delimanolis
12
Des questions comme celle-ci, qui n'améliorent pas la base de données mais n'existent que sous forme d'appât, sont un moyen infaillible d'annuler le jeu Hat à l'avenir. Veuillez ne pas ruiner le jeu en se prostituant.
Blazemonger
Réponses:
256
Le nombre 4946144450195624correspond à 64 bits, sa représentation binaire est:
Le programme décode un caractère pour chaque groupe de 5 bits, de droite à gauche
00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000
d | l | r | o | w | | o | l | l | e | h
Codification 5 bits
Pour 5 bits, il est possible de représenter 2⁵ = 32 caractères. L'alphabet anglais contient 26 lettres, cela laisse de la place pour 32 - 26 = 6 symboles en dehors des lettres. Avec ce schéma de codification, vous pouvez avoir les 26 lettres anglaises (une seule casse) et 6 symboles (en étant un espace parmi eux).
Description de l'algorithme
Le >>= 5dans la boucle for saute de groupe en groupe, puis le groupe de 5 bits est isolé ET en ajoutant le numéro avec le masque 31₁₀ = 11111₂dans la phrasel & 31
Maintenant, le code mappe la valeur 5 bits à son caractère ascii 7 bits correspondant. C'est la partie la plus délicate, vérifiez les représentations binaires pour les lettres minuscules de l'alphabet dans le tableau suivant:
ascii | ascii | ascii | algorithm
character | decimal value | binary value | 5-bit codification
--------------------------------------------------------------
space | 32 | 0100000 | 11111
a | 97 | 1100001 | 00001
b | 98 | 1100010 | 00010
c | 99 | 1100011 | 00011
d | 100 | 1100100 | 00100
e | 101 | 1100101 | 00101
f | 102 | 1100110 | 00110
g | 103 | 1100111 | 00111
h | 104 | 1101000 | 01000
i | 105 | 1101001 | 01001
j | 106 | 1101010 | 01010
k | 107 | 1101011 | 01011
l | 108 | 1101100 | 01100
m | 109 | 1101101 | 01101
n | 110 | 1101110 | 01110
o | 111 | 1101111 | 01111
p | 112 | 1110000 | 10000
q | 113 | 1110001 | 10001
r | 114 | 1110010 | 10010
s | 115 | 1110011 | 10011
t | 116 | 1110100 | 10100
u | 117 | 1110101 | 10101
v | 118 | 1110110 | 10110
w | 119 | 1110111 | 10111
x | 120 | 1111000 | 11000
y | 121 | 1111001 | 11001
z | 122 | 1111010 | 11010
Ici, vous pouvez voir que les caractères ascii que nous voulons mapper commencent par le jeu de 7e et 6e bits ( 11xxxxx₂) (sauf pour l'espace, qui n'a que le 6e bit activé), vous pouvez ORla codification 5 bits avec 96( 96₁₀ = 1100000₂) et cela devrait être assez pour faire le mappage, mais cela ne fonctionnerait pas pour l'espace (sacré espace!)
Maintenant, nous savons qu'il faut prendre un soin particulier pour traiter l'espace en même temps que les autres caractères. Pour ce faire, le code active le 7ème bit (mais pas le 6ème) sur le groupe de 5 bits extrait avec un OR 64 64₁₀ = 1000000₂( l & 31 | 64).
Jusqu'à présent, le groupe de 5 bits est de la forme: 10xxxxx₂(l'espace serait 1011111₂ = 95₁₀). Si nous pouvons mapper l'espace à d' 0autres valeurs qui n'affectent pas d'autres valeurs, alors nous pouvons activer le 6ème bit et ce devrait être tout. Voici ce que la mod 95partie vient de jouer, l'espace est 1011111₂ = 95₁₀, en utilisant l'opération de mod, (l & 31 | 64) % 95)seul l'espace retourne 0, et après cela, le code active le 6ème bit en ajoutant 32₁₀ = 100000₂
au résultat précédent, ((l & 31 | 64) % 95) + 32)transformant la valeur 5 bits en un ascii valide personnage
isolates 5 bits --+ +---- takes 'space' (and only 'space') back to 0
| |
v v
(l & 31 | 64) % 95) + 32
^ ^
turns the | |
7th bit on ------+ +--- turns the 6th bit on
Le code suivant effectue le processus inverse, étant donné une chaîne en minuscules (max 12 caractères), retourne la valeur de 64 bits qui pourrait être utilisée avec le code de l'OP:
publicclass D {publicstaticvoid main(String... args){String v ="hello test";int len =Math.min(12, v.length());long res =0L;for(int i =0; i < len; i++){long c =(long) v.charAt(i)&31;
res |=((((31- c)/31)*31)| c)<<5* i;}System.out.println(res);}}
Les caractères ASCII standard visibles sont compris entre 32 et 127.
C'est pourquoi vous voyez 32 et 95 (127 - 32) ici.
En fait, chaque caractère est mappé ici sur 5 bits (vous pouvez trouver ce qu'est une combinaison de 5 bits pour chaque caractère), puis tous les bits sont concaténés pour former un grand nombre.
Les longs positifs sont des nombres de 63 bits, suffisamment grands pour contenir une forme cryptée de 12 caractères. Il est donc assez grand pour contenir Hello word, mais pour des textes plus volumineux, vous utiliserez des nombres plus grands, voire un BigInteger.
Dans une application, nous voulions transférer des caractères anglais visibles, des caractères persans et des symboles via SMS. Comme vous le voyez, il existe 32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127des valeurs possibles, qui peuvent être représentées avec 7 bits.
Nous avons converti chaque caractère UTF-8 (16 bits) en 7 bits et obtenu un taux de compression de plus de 56%. Nous pourrions donc envoyer des SMS avec deux fois la longueur dans le même nombre de SMS. (C'est en quelque sorte la même chose qui s'est produite ici).
Vous avez encodé des caractères sous forme de valeurs 5 bits et en avez compressé 11 en 64 bits.
(packedValues >> 5*i) & 31 est la i-ième valeur codée avec une plage de 0 à 31.
Le plus dur, comme vous le dites, est d'encoder l'espace. Les lettres minuscules anglaises occupent la plage contiguë 97-122 en Unicode (et ascii, et la plupart des autres encodages), mais l'espace est de 32.
Pour surmonter cela, vous avez utilisé une certaine arithmétique. ((x+64)%95)+32est presque le même que x + 96(notez à quel point OR au niveau du bit est équivalent à l'addition, dans ce cas), mais lorsque x = 31, nous obtenons 32.
Vous devriez expliquer ce que vous faites, au lieu de publier une autre énigme
Aleksandr Dubinsky
1
Je vous suggère d'investir un peu d'efforts dans la recherche d'un site (peut-être un Beta StackExchange?) Où contribuer des énigmes amusantes est le bienvenu. Stack Overflow est un site de questions-réponses avec un objectif strictement appliqué.
Marko Topolnik
1
@MarkoTopolnik Je détesterais vivre dans un monde où toutes les règles ou toutes les priorités étaient si strictement appliquées qu'elles ne permettent aucune exception. Sans oublier qu'il existe d'innombrables exceptions de ce type sur SO.
גלעד ברקן
1
Moi aussi, mais SO est un tel monde dans une mesure inhabituellement grande. Bien sûr, il y a des exceptions même ici, mais elles ne sont pas les bienvenues .
Marko Topolnik
1
Quinze autres partageaient le sentiment d'Alexandr. Et vous avez raison de souligner que la question elle-même est inappropriée pour SO, comme indiqué ci-dessous.
Marko Topolnik
3
Sans Oracleétiquette, il était difficile de voir cette question. La prime active m'a amené ici. Je souhaite que la question ait également d'autres balises technologiques pertinentes :-(
Je travaille principalement avec Oracle database, donc j'utiliserais quelques Oracleconnaissances pour interpréter et expliquer :-)
Convertissons le nombre 4946144450195624en binary. Pour cela, j'utilise un petit functiondec2bin appelé decimal-to-binary .
SQL> CREATE OR REPLACE FUNCTION dec2bin (N in number) RETURN varchar2 IS
2 binval varchar2(64);3 N2 number := N;4 BEGIN
5while( N2 >0) loop
6 binval := mod(N2,2)|| binval;7 N2 := trunc( N2 /2);8 end loop;9return binval;10 END dec2bin;11/Function created.
SQL> show errors
No errors.
SQL>
Utilisons la fonction pour obtenir la valeur binaire -
SQL> SELECT dec2bin(4946144450195624) FROM dual;
DEC2BIN(4946144450195624)--------------------------------------------------------------------------------10001100100100111110111111110111101100011000010101000
SQL>
Maintenant, le hic, c'est la 5-bitconversion. Commencez à regrouper de droite à gauche avec 5 chiffres dans chaque groupe. On a :-
Nous serions finalement laissés avec seulement 3 chiffres entiers à droite. Parce que nous avons eu un total de 53 chiffres dans la conversion binaire.
SQL> SELECT LENGTH(dec2bin(4946144450195624)) FROM dual;
LENGTH(DEC2BIN(4946144450195624))---------------------------------53
SQL>
hello worldle total a 11 caractères (y compris l'espace), nous devons donc ajouter 2 bits au dernier groupe où il ne nous restait que 3 bits après le regroupement.
Maintenant, nous devons le convertir en valeur ascii 7 bits. Pour les personnages, c'est facile, il suffit de définir le 6ème et le 7ème bit. Ajoutez 11à chaque groupe de 5 bits ci-dessus à gauche.
Interprétons les valeurs binaires, j'utiliserai binary to decimal conversion function.
SQL> CREATE OR REPLACE FUNCTION bin2dec (binval in char) RETURN number IS
2 i number;3 digits number;4 result number :=0;5 current_digit char(1);6 current_digit_dec number;7 BEGIN
8 digits := length(binval);9for i in 1..digits loop
10 current_digit := SUBSTR(binval, i,1);11 current_digit_dec := to_number(current_digit);12 result :=(result *2)+ current_digit_dec;13 end loop;14return result;15 END bin2dec;16/Function created.
SQL> show errors;No errors.
SQL>
Regardons chaque valeur binaire -
SQL> set linesize 1000
SQL>
SQL> SELECT bin2dec('1100100') val,2 bin2dec('1101100') val,3 bin2dec('1110010') val,4 bin2dec('1101111') val,5 bin2dec('1110111') val,6 bin2dec('1111111') val,7 bin2dec('1101111') val,8 bin2dec('1101100') val,9 bin2dec('1101100') val,10 bin2dec('1100101') val,11 bin2dec('1101000') val
12 FROM dual;
VAL VAL VAL VAL VAL VAL VAL VAL VAL VAL VAL
--------------------------------------------------------------------------------------------------------------100108114111119127111108108101104
SQL>
Regardons quels personnages ils sont: -
SQL> SELECT chr(bin2dec('1100100')) character,2 chr(bin2dec('1101100')) character,3 chr(bin2dec('1110010')) character,4 chr(bin2dec('1101111')) character,5 chr(bin2dec('1110111')) character,6 chr(bin2dec('1111111')) character,7 chr(bin2dec('1101111')) character,8 chr(bin2dec('1101100')) character,9 chr(bin2dec('1101100')) character,10 chr(bin2dec('1100101')) character,11 chr(bin2dec('1101000')) character
12 FROM dual;
CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER
---------------------------------------------------------------------------------------------------
d l r o w ⌂ o l l e h
SQL>
Alors, qu'obtenons-nous dans la sortie?
dlrow ⌂ olleh
C'est hello⌂world à l'envers. Le seul problème est l' espace . Et la raison est bien expliquée par @higuaro dans sa réponse. Honnêtement, je ne pouvais pas interpréter moi-même la question de l'espace du premier coup, jusqu'à ce que je voie l'explication donnée dans sa réponse.
Réponses:
Le nombre
4946144450195624
correspond à 64 bits, sa représentation binaire est:Le programme décode un caractère pour chaque groupe de 5 bits, de droite à gauche
Codification 5 bits
Pour 5 bits, il est possible de représenter 2⁵ = 32 caractères. L'alphabet anglais contient 26 lettres, cela laisse de la place pour 32 - 26 = 6 symboles en dehors des lettres. Avec ce schéma de codification, vous pouvez avoir les 26 lettres anglaises (une seule casse) et 6 symboles (en étant un espace parmi eux).
Description de l'algorithme
Le
>>= 5
dans la boucle for saute de groupe en groupe, puis le groupe de 5 bits est isolé ET en ajoutant le numéro avec le masque31₁₀ = 11111₂
dans la phrasel & 31
Maintenant, le code mappe la valeur 5 bits à son caractère ascii 7 bits correspondant. C'est la partie la plus délicate, vérifiez les représentations binaires pour les lettres minuscules de l'alphabet dans le tableau suivant:
Ici, vous pouvez voir que les caractères ascii que nous voulons mapper commencent par le jeu de 7e et 6e bits (
11xxxxx₂
) (sauf pour l'espace, qui n'a que le 6e bit activé), vous pouvezOR
la codification 5 bits avec96
(96₁₀ = 1100000₂
) et cela devrait être assez pour faire le mappage, mais cela ne fonctionnerait pas pour l'espace (sacré espace!)Maintenant, nous savons qu'il faut prendre un soin particulier pour traiter l'espace en même temps que les autres caractères. Pour ce faire, le code active le 7ème bit (mais pas le 6ème) sur le groupe de 5 bits extrait avec un OR 64
64₁₀ = 1000000₂
(l & 31 | 64
).Jusqu'à présent, le groupe de 5 bits est de la forme:
10xxxxx₂
(l'espace serait1011111₂ = 95₁₀
). Si nous pouvons mapper l'espace à d'0
autres valeurs qui n'affectent pas d'autres valeurs, alors nous pouvons activer le 6ème bit et ce devrait être tout. Voici ce que lamod 95
partie vient de jouer, l'espace est1011111₂ = 95₁₀
, en utilisant l'opération de mod,(l & 31 | 64) % 95)
seul l'espace retourne0
, et après cela, le code active le 6ème bit en ajoutant32₁₀ = 100000₂
au résultat précédent,((l & 31 | 64) % 95) + 32)
transformant la valeur 5 bits en un ascii valide personnageLe code suivant effectue le processus inverse, étant donné une chaîne en minuscules (max 12 caractères), retourne la valeur de 64 bits qui pourrait être utilisée avec le code de l'OP:
la source
Ajout de la valeur aux réponses ci-dessus. Le script groovy suivant imprime les valeurs intermédiaires.
C'est ici
la source
Intéressant!
Les caractères ASCII standard visibles sont compris entre 32 et 127.
C'est pourquoi vous voyez 32 et 95 (127 - 32) ici.
En fait, chaque caractère est mappé ici sur 5 bits (vous pouvez trouver ce qu'est une combinaison de 5 bits pour chaque caractère), puis tous les bits sont concaténés pour former un grand nombre.
Les longs positifs sont des nombres de 63 bits, suffisamment grands pour contenir une forme cryptée de 12 caractères. Il est donc assez grand pour contenir
Hello word
, mais pour des textes plus volumineux, vous utiliserez des nombres plus grands, voire un BigInteger.Dans une application, nous voulions transférer des caractères anglais visibles, des caractères persans et des symboles via SMS. Comme vous le voyez, il existe
32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127
des valeurs possibles, qui peuvent être représentées avec 7 bits.Nous avons converti chaque caractère UTF-8 (16 bits) en 7 bits et obtenu un taux de compression de plus de 56%. Nous pourrions donc envoyer des SMS avec deux fois la longueur dans le même nombre de SMS. (C'est en quelque sorte la même chose qui s'est produite ici).
la source
| 64
fait.Vous obtenez un résultat qui se trouve être une
char
représentation des valeurs ci-dessousla source
Vous avez encodé des caractères sous forme de valeurs 5 bits et en avez compressé 11 en 64 bits.
(packedValues >> 5*i) & 31
est la i-ième valeur codée avec une plage de 0 à 31.Le plus dur, comme vous le dites, est d'encoder l'espace. Les lettres minuscules anglaises occupent la plage contiguë 97-122 en Unicode (et ascii, et la plupart des autres encodages), mais l'espace est de 32.
Pour surmonter cela, vous avez utilisé une certaine arithmétique.
((x+64)%95)+32
est presque le même quex + 96
(notez à quel point OR au niveau du bit est équivalent à l'addition, dans ce cas), mais lorsque x = 31, nous obtenons32
.la source
Il imprime "hello world" pour une raison similaire:
mais pour une raison quelque peu différente de celle-ci:
la source
Sans
Oracle
étiquette, il était difficile de voir cette question. La prime active m'a amené ici. Je souhaite que la question ait également d'autres balises technologiques pertinentes :-(Je travaille principalement avec
Oracle database
, donc j'utiliserais quelquesOracle
connaissances pour interpréter et expliquer :-)Convertissons le nombre
4946144450195624
enbinary
. Pour cela, j'utilise un petitfunction
dec2bin appelé decimal-to-binary .Utilisons la fonction pour obtenir la valeur binaire -
Maintenant, le hic, c'est la
5-bit
conversion. Commencez à regrouper de droite à gauche avec 5 chiffres dans chaque groupe. On a :-Nous serions finalement laissés avec seulement 3 chiffres entiers à droite. Parce que nous avons eu un total de 53 chiffres dans la conversion binaire.
hello world
le total a 11 caractères (y compris l'espace), nous devons donc ajouter 2 bits au dernier groupe où il ne nous restait que 3 bits après le regroupement.Donc, maintenant nous avons: -
Maintenant, nous devons le convertir en valeur ascii 7 bits. Pour les personnages, c'est facile, il suffit de définir le 6ème et le 7ème bit. Ajoutez
11
à chaque groupe de 5 bits ci-dessus à gauche.Ça donne :-
Interprétons les valeurs binaires, j'utiliserai
binary to decimal conversion function
.Regardons chaque valeur binaire -
Regardons quels personnages ils sont: -
Alors, qu'obtenons-nous dans la sortie?
dlrow ⌂ olleh
C'est hello⌂world à l'envers. Le seul problème est l' espace . Et la raison est bien expliquée par @higuaro dans sa réponse. Honnêtement, je ne pouvais pas interpréter moi-même la question de l'espace du premier coup, jusqu'à ce que je voie l'explication donnée dans sa réponse.
la source
J'ai trouvé le code légèrement plus facile à comprendre lorsqu'il est traduit en PHP, comme suit:
Voir le code en direct
la source
out.println ((char) (((l & 31 | 64)% 95) + 32/1002439 * 1002439));
Pour faire des bouchons: 3
la source