Я имею в виду, вы можете понять это самостоятельно.
Сотириос Делиманолис
30
Да. Я признаю ... я ловлю шляпы :)
Богемный
6
Я думаю, что видел этот вопрос, заданный здесь раньше ..
Zavior
6
@ Оли. Для этого должна быть шляпа.
Сотириос Делиманолис
12
Подобные вопросы, которые не улучшают базу данных, а существуют исключительно как клик-приманки, являются верным способом отменить игру Hat в будущем. Пожалуйста, не портите игру, желая этого.
Blazemonger
Ответы:
256
Число 4946144450195624соответствует 64 битам, его двоичное представление:
Программа декодирует символ для каждой 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 происходит переход от группы к группе, затем 5-битная группа изолируется И начинает вычислять число с маской 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-го бита set ( 11xxxxx₂) (кроме пробела, в котором включен только 6-й бит), вы можете OR5-битную кодификацию с 96( 96₁₀ = 1100000₂), и это должно быть достаточно, чтобы сделать отображение, но это не сработает для пространства (черт побери!)
Теперь мы знаем, что особое внимание нужно уделить обработке пространства одновременно с другими персонажами. Для этого код включает 7-й бит (но не 6-й) в извлеченной 5-битной группе с помощью ИЛИ 64 64₁₀ = 1000000₂( l & 31 | 64).
Пока 5-битная группа имеет вид: 10xxxxx₂(пробел будет 1011111₂ = 95₁₀). Если мы можем отобразить пространство так, чтобы оно 0не влияло на другие значения, то мы можем включить 6-й бит, и это все. Вот то, что mod 95играет роль, пробел 1011111₂ = 95₁₀, с помощью операции мод (l & 31 | 64) % 95)возвращается только пробел 0, и после этого код включает 6-й бит, добавляя 32₁₀ = 100000₂
к предыдущему результату, ((l & 31 | 64) % 95) + 32)преобразовывая 5-битное значение в действительный 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 символов), возвращает значение длиной 64 бита, которое можно использовать с кодом 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);}}
Стандартные символы ASCII, которые видны, находятся в диапазоне от 32 до 127.
Вот почему вы видите 32 и 95 (127 - 32) там.
Фактически каждый символ сопоставляется с 5 битами здесь (вы можете найти, что такое 5-битная комбинация для каждого символа), а затем все биты объединяются в большое число.
Положительные длинные значения - это 63-разрядные числа, достаточно большие, чтобы содержать зашифрованную форму из 12 символов. Таким образом, он достаточно большой для хранения Hello word, но для больших текстов вы должны использовать большие числа или даже BigInteger.
В приложении мы хотели передать видимые английские символы, персидские символы и символы через SMS. Как видите, есть 32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127возможные значения, которые могут быть представлены 7 битами.
Мы преобразовали каждый символ UTF-8 (16 бит) в 7 бит и получили коэффициент сжатия более 56%. Таким образом, мы могли бы отправлять тексты с двойной длиной в одном и том же количестве SMS-сообщений. (Здесь как-то так же и произошло).
Вы кодировали символы как 5-битные значения и упаковали 11 из них в 64-битную длину.
(packedValues >> 5*i) & 31 это i-е закодированное значение в диапазоне 0-31.
Сложная часть, как вы говорите, это кодирование пространства. Английские буквы в нижнем регистре занимают непрерывный диапазон 97-122 в Unicode (и ascii, и в большинстве других кодировок), но пробел равен 32.
Чтобы преодолеть это, вы использовали некоторую арифметику. ((x+64)%95)+32почти так же, как x + 96(обратите внимание, что в этом случае побитовое ИЛИ эквивалентно сложению), но когда x = 31, мы получаем 32.
Вы должны объяснить, что вы делаете, вместо того, чтобы публиковать еще одну загадку
Александр Дубинский
1
Я предлагаю вам приложить некоторые усилия, чтобы найти сайт (возможно, Beta StackExchange?), Где приветствуются веселые загадки. Stack Overflow - это сайт вопросов и ответов со строгим контролем.
Марко Топольник
1
@MarkoTopolnik Я бы не хотел жить в мире, где все правила или акценты строго соблюдались, чтобы никогда не допускать никаких исключений. Не говоря уже о том, что на SO существует множество подобных исключений.
גלעד ברקן
1
Я бы тоже, но ТАК такой мир необычайно велик. Конечно, есть исключения даже здесь, но они не приветствуются .
Марко Топольник
1
Еще 15 поделились мнением Александра. И вы правы, указывая на то, что сам вопрос не подходит для SO, как прокомментировано ниже.
Марко Топольник
3
Без Oracle тега было сложно увидеть этот вопрос. Активная щедрость привела меня сюда. Хотелось бы, чтобы у вопроса были и другие соответствующие технологические теги :-(
Я в основном работаю с Oracle database, поэтому я бы использовал некоторые Oracleзнания, чтобы интерпретировать и объяснить :-)
Давайте преобразовать число 4946144450195624в binary. Для этого я использую маленький functiondec2bin, то есть десятичный в двоичный .
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>
Давайте использовать функцию, чтобы получить двоичное значение -
SQL> SELECT dec2bin(4946144450195624) FROM dual;
DEC2BIN(4946144450195624)--------------------------------------------------------------------------------10001100100100111110111111110111101100011000010101000
SQL>
Теперь подвох - это 5-bitпреобразование. Начните группировку справа налево с 5 цифрами в каждой группе. Мы получили :-
Мы были бы наконец оставлены только с 3 цифрами в конце справа. Потому что у нас было всего 53 цифры в двоичном преобразовании.
SQL> SELECT LENGTH(dec2bin(4946144450195624)) FROM dual;
LENGTH(DEC2BIN(4946144450195624))---------------------------------53
SQL>
hello worldВсего 11 символов (включая пробел), поэтому нам нужно добавить 2 бита в последнюю группу, в которой мы остались, всего 3 бита после группировки.
Теперь нам нужно преобразовать его в 7-битное значение ascii. Для персонажей это просто, нам нужно просто установить 6-й и 7-й бит. Добавьте 11к каждой 5-битной группе выше слева.
Давайте интерпретировать двоичные значения, я буду использовать 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>
Давайте посмотрим на каждое двоичное значение -
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>
Давайте посмотрим, что это за персонажи:
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>
Итак, что мы получаем в результате?
Dlrow ⌂ Olleh
Это привет мир в обратном порядке. Единственная проблема - это пространство . И причина хорошо объяснена @higuaro в своем ответе. Я, честно говоря, не мог интерпретировать проблему космоса сам с первой попытки, пока не увидел объяснение, данное в его ответе.
Ответы:
Число
4946144450195624
соответствует 64 битам, его двоичное представление:Программа декодирует символ для каждой 5-битной группы справа налево
5-битная кодификация
Для 5 битов можно представить 2⁵ = 32 символа. Английский алфавит содержит 26 букв, это оставляет место для 32 - 26 = 6 символов, кроме букв. С этой схемой кодификации вы можете иметь все 26 (один случай) английских букв и 6 символов (будучи пробелом среди них).
Описание алгоритма
В
>>= 5
цикле for происходит переход от группы к группе, затем 5-битная группа изолируется И начинает вычислять число с маской31₁₀ = 11111₂
в предложении.l & 31
Теперь код отображает 5-битное значение на соответствующий ему 7-битный символ ascii. Это сложная часть, проверьте двоичные представления для строчных букв алфавита в следующей таблице:
Здесь вы можете видеть, что символы ascii, которые мы хотим отобразить, начинаются с 7-го и 6-го бита set (
11xxxxx₂
) (кроме пробела, в котором включен только 6-й бит), вы можетеOR
5-битную кодификацию с96
(96₁₀ = 1100000₂
), и это должно быть достаточно, чтобы сделать отображение, но это не сработает для пространства (черт побери!)Теперь мы знаем, что особое внимание нужно уделить обработке пространства одновременно с другими персонажами. Для этого код включает 7-й бит (но не 6-й) в извлеченной 5-битной группе с помощью ИЛИ 64
64₁₀ = 1000000₂
(l & 31 | 64
).Пока 5-битная группа имеет вид:
10xxxxx₂
(пробел будет1011111₂ = 95₁₀
). Если мы можем отобразить пространство так, чтобы оно0
не влияло на другие значения, то мы можем включить 6-й бит, и это все. Вот то, чтоmod 95
играет роль, пробел1011111₂ = 95₁₀
, с помощью операции мод(l & 31 | 64) % 95)
возвращается только пробел0
, и после этого код включает 6-й бит, добавляя32₁₀ = 100000₂
к предыдущему результату,((l & 31 | 64) % 95) + 32)
преобразовывая 5-битное значение в действительный ascii персонажСледующий код выполняет обратный процесс, учитывая строчную строку (максимум 12 символов), возвращает значение длиной 64 бита, которое можно использовать с кодом OP:
источник
Добавление некоторой ценности к ответам выше. Следующий скриптовый скрипт печатает промежуточные значения.
Вот
источник
Интересный!
Стандартные символы ASCII, которые видны, находятся в диапазоне от 32 до 127.
Вот почему вы видите 32 и 95 (127 - 32) там.
Фактически каждый символ сопоставляется с 5 битами здесь (вы можете найти, что такое 5-битная комбинация для каждого символа), а затем все биты объединяются в большое число.
Положительные длинные значения - это 63-разрядные числа, достаточно большие, чтобы содержать зашифрованную форму из 12 символов. Таким образом, он достаточно большой для хранения
Hello word
, но для больших текстов вы должны использовать большие числа или даже BigInteger.В приложении мы хотели передать видимые английские символы, персидские символы и символы через SMS. Как видите, есть
32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127
возможные значения, которые могут быть представлены 7 битами.Мы преобразовали каждый символ UTF-8 (16 бит) в 7 бит и получили коэффициент сжатия более 56%. Таким образом, мы могли бы отправлять тексты с двойной длиной в одном и том же количестве SMS-сообщений. (Здесь как-то так же и произошло).
источник
| 64
делает.Вы получаете результат, который оказывается
char
представлением ниже значенийисточник
Вы кодировали символы как 5-битные значения и упаковали 11 из них в 64-битную длину.
(packedValues >> 5*i) & 31
это i-е закодированное значение в диапазоне 0-31.Сложная часть, как вы говорите, это кодирование пространства. Английские буквы в нижнем регистре занимают непрерывный диапазон 97-122 в Unicode (и ascii, и в большинстве других кодировок), но пробел равен 32.
Чтобы преодолеть это, вы использовали некоторую арифметику.
((x+64)%95)+32
почти так же, какx + 96
(обратите внимание, что в этом случае побитовое ИЛИ эквивалентно сложению), но когда x = 31, мы получаем32
.источник
Он печатает «привет мир» по той же причине, что и делает:
но по несколько иной причине, чем эта:
источник
Без
Oracle
тега было сложно увидеть этот вопрос. Активная щедрость привела меня сюда. Хотелось бы, чтобы у вопроса были и другие соответствующие технологические теги :-(Я в основном работаю с
Oracle database
, поэтому я бы использовал некоторыеOracle
знания, чтобы интерпретировать и объяснить :-)Давайте преобразовать число
4946144450195624
вbinary
. Для этого я использую маленькийfunction
dec2bin, то есть десятичный в двоичный .Давайте использовать функцию, чтобы получить двоичное значение -
Теперь подвох - это
5-bit
преобразование. Начните группировку справа налево с 5 цифрами в каждой группе. Мы получили :-Мы были бы наконец оставлены только с 3 цифрами в конце справа. Потому что у нас было всего 53 цифры в двоичном преобразовании.
hello world
Всего 11 символов (включая пробел), поэтому нам нужно добавить 2 бита в последнюю группу, в которой мы остались, всего 3 бита после группировки.Итак, теперь у нас есть: -
Теперь нам нужно преобразовать его в 7-битное значение ascii. Для персонажей это просто, нам нужно просто установить 6-й и 7-й бит. Добавьте
11
к каждой 5-битной группе выше слева.Это дает:
Давайте интерпретировать двоичные значения, я буду использовать
binary to decimal conversion function
.Давайте посмотрим на каждое двоичное значение -
Давайте посмотрим, что это за персонажи:
Итак, что мы получаем в результате?
Dlrow ⌂ Olleh
Это привет мир в обратном порядке. Единственная проблема - это пространство . И причина хорошо объяснена @higuaro в своем ответе. Я, честно говоря, не мог интерпретировать проблему космоса сам с первой попытки, пока не увидел объяснение, данное в его ответе.
источник
Я нашел код немного легче понять при переводе на PHP, как показано ниже:
Смотрите живой код
источник
out.println ((символ) (((l & 31 | 64)% 95) + 32/1002439 * 1002439));
Чтобы сделать это заглавными буквами: 3
источник