programing

이 인쇄물 "안녕하세요"는 어떻게 쓰여져 있나요?

prostudy 2022. 8. 30. 21:31
반응형

이 인쇄물 "안녕하세요"는 어떻게 쓰여져 있나요?

나는 이상한 점을 발견했다.

for (long l = 4946144450195624l; l > 0; l >>= 5)
    System.out.print((char) (((l & 31 | 64) % 95) + 32));

출력:

hello world

이게 어떻게 작동하나요?

★★4946144450195624 그 은 다음과 같습니다.

 10001100100100111110111111110111101100011000010101000

프로그램은 오른쪽에서 왼쪽으로 5비트 그룹별로 문자를 디코딩합니다.

 00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000
   d  |  l  |  r  |  o  |  w  |     |  o  |  l  |  l  |  e  |  h

5비트 코드화

5비트의 경우 2µ = 32자를 나타낼 수 있습니다.영어 알파벳은 26자를 포함하며, 32 - 26 = 6개의 기호를 사용할 수 있는 공간이 있습니다.이 코드화 방식에서는 26개의 영문자와 6개의 기호(스페이스 포함)를 모두 사용할 수 있습니다.

알고리즘 설명

>>= 5 "for-loop"을 .31₁₀ = 11111₂l & 31

이제 코드는 5비트 값을 대응하는 7비트 ASCII 문자에 매핑합니다.이것은 어려운 부분입니다.다음 표의 소문자 알파벳 바이너리 표현을 확인해 주세요.

  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

ASCII 7번째와 6번째 비트세트)로 을 알 수 .11xxxxx₂스페이스는 온이 되어 만, 과 같이 할 수 있습니다(「6비트」).OR 5비트 코드화96 )96₁₀ = 1100000₂매핑에는 충분하지만 공간에는 적합하지 않습니다(공간에는 적합하지 않습니다.

이제 우리는 다른 캐릭터들과 동시에 공간을 처리하기 위해 특별한 주의를 기울여야 한다는 것을 알게 되었다.가 아님)를 OR 64로 합니다.OR 64는 "5"로 "7"로 설정합니다(6번째 비트는 ).64₁₀ = 1000000₂ )l & 31 | 64를 참조해 주세요.

은 5비트 10xxxxx₂는 (스페이스)입니다.1011111₂ = 95₁₀0다른 값에 영향을 주지 않으면 6번째 비트를 켜면 됩니다., 은요.mod 95은 플레이를 은 「스페이스」, 「스페이스」입니다.1011111₂ = 95₁₀ 조작을 하여 mod " " 를 사용합니다(l & 31 | 64) % 95)0후 , 비트가 켜집니다.32₁₀ = 100000₂결과에 , 「」라고 하는 것이 .((l & 31 | 64) % 95) + 32)한 ASCII 의 ASCII 문자 변환

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

다음 코드는 소문자 문자열(최대 12자)이 지정되면 OP 코드에서 사용할 수 있는 64비트 길이의 값을 반환합니다.

public class D {
    public static void 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);
    }
}    

위의 답변에 약간의 가치를 더합니다.다음 groovy 스크립트는 중간 값을 인쇄합니다.

String getBits(long l) {
return Long.toBinaryString(l).padLeft(8,'0');
}

for (long l = 4946144450195624l; l > 0; l >>= 5){
    println ''
    print String.valueOf(l).toString().padLeft(16,'0')
    print '|'+ getBits((l & 31 ))
    print '|'+ getBits(((l & 31 | 64)))
    print '|'+ getBits(((l & 31 | 64)  % 95))
    print '|'+ getBits(((l & 31 | 64)  % 95 + 32))

    print '|';
    System.out.print((char) (((l & 31 | 64) % 95) + 32));
}

여기 있어요.

4946144450195624|00001000|01001000|01001000|01101000|h
0154567014068613|00000101|01000101|01000101|01100101|e
0004830219189644|00001100|01001100|01001100|01101100|l
0000150944349676|00001100|01001100|01001100|01101100|l
0000004717010927|00001111|01001111|01001111|01101111|o
0000000147406591|00011111|01011111|00000000|00100000| 
0000000004606455|00010111|01010111|01010111|01110111|w
0000000000143951|00001111|01001111|01001111|01101111|o
0000000000004498|00010010|01010010|01010010|01110010|r
0000000000000140|00001100|01001100|01001100|01101100|l
0000000000000004|00000100|01000100|01000100|01100100|d

재밌다!

표시되는 표준 ASCII 문자의 범위는 32 ~127입니다

그래서 32와 95(127 - 32)가 표시됩니다.

실제로 여기서 각 문자는 5비트에 매핑되어 있습니다(각 문자에 대해 5비트 조합이 무엇인지 확인할 수 있습니다). 그리고 나서 모든 비트가 연결되어 큰 숫자를 형성합니다.

양의 긴 길이는 63비트 숫자로 12자의 암호화된 형식을 유지할 수 있습니다.그래서 그것은 충분히 크고Hello word, 더 큰 더해야 합니다.


영어 , SMS로 플플케 、 로로 、 르로 、 로로 、 로로 、 로로 、 로로 、 SMS 로로 in 。 보다시피 다음과 같다.32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 1277시 정각

각 UTF-8(16비트) 문자를 7비트로 변환하여 56% 이상의 압축률을 얻었습니다.같은 수의 SMS로 2배 길이의 문자를 보낼 수 있습니다(이것도 같은 일이었습니다).

가 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」char 값의

104 -> h
101 -> e
108 -> l
108 -> l
111 -> o
32  -> (space)
119 -> w
111 -> o
114 -> r
108 -> l
100 -> d

문자를 5비트 값으로 인코딩하고 그 중 11개를 64비트 길이로 압축했습니다.

(packedValues >> 5*i) & 310에서 31까지입니다.

어려운 부분은, 말씀하신 대로, 공간을 인코딩하는 것입니다.소문자 영문자는 Unicode(및 ASCII 및 기타 대부분의 인코딩)에서 97~122 의 연속 범위를 차지하지만, 공백은 32 입니다.

이것을 극복하기 위해, 당신은 약간의 산수를 사용했다. ((x+64)%95)+32 x + 96덧셈과 해 주세요).단, x 때 (즉, OR은 OR입니다.)는 x=31이 됩니다.32.

다음과 같은 이유로 "hello world"가 출력됩니다.

for (int k=1587463874; k>0; k>>=3)
     System.out.print((char) (100 + Math.pow(2,2*(((k&7^1)-1)>>3 + 1) + (k&7&3)) + 10*((k&7)>>2) + (((k&7)-7)>>3) + 1 - ((-(k&7^5)>>3) + 1)*80));

하지만 이것과는 좀 다른 이유:

for (int k=2011378; k>0; k>>=2)
    System.out.print((char) (110 + Math.pow(2,2*(((k^1)-1)>>21 + 1) + (k&3)) - ((k&8192)/8192 + 7.9*(-(k^1964)>>21) - .1*(-((k&35)^35)>>21) + .3*(-((k&120)^120)>>21) + (-((k|7)^7)>>21) + 9.1)*10));

★★★ Oracle태 、 이 、 기 、 기 、 려 、 요요요요 。현상금이 날 여기로 데려왔어질문에는 다른 관련 기술 태그도 첨부되어 있으면 좋을 것 같습니다.- )

는 주로 는로와 함께 .Oracle database그래서 좀 쓸게요.Oracle represidence :- )를.

이 해 볼까요?4946144450195624binary그래서 작은 거 쓰고functiondec2bin, 즉 10진수에서 소수점까지라고 불립니다.

SQL> CREATE OR REPLACE FUNCTION dec2bin (N in number) RETURN varchar2 IS
  2    binval varchar2(64);
  3    N2     number := N;
  4  BEGIN
  5    while ( N2 > 0 ) loop
  6       binval := mod(N2, 2) || binval;
  7       N2 := trunc( N2 / 2 );
  8    end loop;
  9    return binval;
 10  END dec2bin;
 11  /

Function created.

SQL> show errors
No errors.
SQL>

함수를 사용하여 2진수 값을 구합니다.

SQL> SELECT dec2bin(4946144450195624) FROM dual;

DEC2BIN(4946144450195624)
--------------------------------------------------------------------------------
10001100100100111110111111110111101100011000010101000

SQL>

, 이제 은 ★★★★★★★★★★★★★★★★★★★★.5-bit 합니다.그룹별로 5자리씩 오른쪽에서 왼쪽으로 그룹화를 시작합니다. 해서 음음음 잖아요.

100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000

오른쪽 끝에 3자리 숫자만 남겨두게다2진수 변환에서 총 53자리 숫자가 나왔기 때문입니다.

SQL> SELECT LENGTH(dec2bin(4946144450195624)) FROM dual;

LENGTH(DEC2BIN(4946144450195624))
---------------------------------
                               53

SQL>

hello worldtotal은 11자(스페이스 포함)이므로 그룹화 후 남은 마지막 그룹에 2비트를 추가해야 합니다.

자, 이제 다음이 있습니다.

00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000

ASCII를 사용하다캐릭터는 6번째와 7번째 비트만 맞추면 돼요.115시 정각

그 결과:-

1100100|1101100|1110010|1101111|1110111|1111111|1101111|1101100|1101100|1100101|1101000

값을 해 볼까요, 는 이 두 가지 을 사용해 보겠습니다.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);
  9    for 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;
 14    return result;
 15  END bin2dec;
 16  /

Function created.

SQL> show errors;
No errors.
SQL>

각 바이너리 값을 살펴보겠습니다.

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
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
       100        108        114        111        119        127        111        108        108     101           104

SQL>

어떤 캐릭터인지 알아보겠습니다.-

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>

출력은 어떻게 됩니까?

d l r o w o o l e h

저것은 헬로월드의 반대입니다.유일한 문제는 공간이다.그리고 그 이유는 @higuaro에 의해 잘 설명되고 있다.솔직히 처음에는 공간 문제를 직접 해석할 수 없었지만, 그의 답변을 보기 전까지는요.

PHP로 번역하면 다음과 같이 조금 알기 쉬웠습니다.

<?php

$result=0;
$bignum = 4946144450195624;
for (; $bignum > 0; $bignum >>= 5){
    $result = (( $bignum & 31 | 64) % 95) + 32;
    echo chr($result);
}

라이브 코드 참조

out.println((char) ((l & 31 | 64) % 95) + 32 / 1002439 * 1002439);

대문자 수: 3

언급URL : https://stackoverflow.com/questions/20720098/how-does-this-print-hello-world

반응형