Saya pikir saya telah melihat pertanyaan ini diajukan di sini sebelumnya ..
Zavior
6
@ Oli Seharusnya ada topi untuk itu.
Sotirios Delimanolis
12
Pertanyaan seperti ini, yang tidak meningkatkan database tetapi hanya ada sebagai clickbait, adalah cara yang pasti untuk membuat game Hat dibatalkan di masa depan. Tolong jangan merusak permainan dengan mengemis untuk itu.
Program mendekode karakter untuk setiap grup 5-bit, dari kanan ke kiri
00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000
d | l | r | o | w | | o | l | l | e | h
Kodifikasi 5-bit
Untuk 5 bit, dimungkinkan mewakili 2⁵ = 32 karakter. Alfabet bahasa Inggris berisi 26 huruf, ini menyisakan ruang untuk 32 - 26 = 6 simbol terpisah dari huruf. Dengan skema kodifikasi ini Anda dapat memiliki semua 26 (satu huruf) huruf bahasa Inggris dan 6 simbol (menjadi spasi di antara mereka).
Deskripsi algoritma
The >>= 5dalam for-loop melompat dari grup ke grup, maka grup 5-bit terisolasi DAN nomor dengan topeng 31₁₀ = 11111₂dalam kalimatl & 31
Sekarang kode memetakan nilai 5-bit ke karakter ascii 7-bit yang sesuai. Ini adalah bagian yang sulit, periksa representasi biner untuk huruf alfabet huruf kecil dalam tabel berikut:
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
Di sini Anda dapat melihat bahwa karakter ascii yang ingin kami petakan dimulai dengan set bit ke-7 dan ke-6 ( 11xxxxx₂) (kecuali untuk ruang, yang hanya memiliki bit ke-6), Anda dapat ORmenggunakan kodifikasi 5-bit dengan 96( 96₁₀ = 1100000₂) dan itu seharusnya cukup untuk melakukan pemetaan, tetapi itu tidak akan berhasil untuk ruang (ruang sialan!)
Sekarang kita tahu bahwa perhatian khusus harus diambil untuk memproses ruang pada saat yang sama dengan karakter lain. Untuk mencapai ini, kode mengaktifkan bit ke-7 (tetapi bukan ke-6) pada grup 5-bit yang diekstraksi dengan OR 64 64₁₀ = 1000000₂( l & 31 | 64).
Sejauh ini kelompok 5-bit berbentuk: 10xxxxx₂(ruang akan 1011111₂ = 95₁₀). Jika kita dapat memetakan ruang untuk 0menghapus nilai-nilai lain, maka kita dapat mengaktifkan bit ke-6 dan itu saja. Inilah mod 95bagian yang harus dimainkan, space 1011111₂ = 95₁₀, menggunakan operasi mod, (l & 31 | 64) % 95)hanya ruang yang kembali 0, dan setelah ini, kode menghidupkan bit ke-6 dengan menambahkan 32₁₀ = 100000₂
ke hasil sebelumnya, ((l & 31 | 64) % 95) + 32)mengubah nilai 5-bit menjadi ascii yang valid karakter
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
Kode berikut melakukan proses invers, diberi string huruf kecil (maks 12 karakter), mengembalikan nilai panjang 64 bit yang dapat digunakan dengan kode 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);}}
Karakter ASCII standar yang terlihat berada dalam kisaran 32 hingga 127.
Itu sebabnya Anda melihat 32, dan 95 (127 - 32) di sana.
Sebenarnya setiap karakter dipetakan ke 5 bit di sini, (Anda dapat menemukan apa kombinasi 5 bit untuk setiap karakter), dan kemudian semua bit digabungkan untuk membentuk angka yang besar.
Panjang positif adalah angka 63 bit, cukup besar untuk menampung bentuk terenkripsi 12 karakter. Jadi cukup besar untuk menampung Hello word, tetapi untuk teks yang lebih besar Anda harus menggunakan angka yang lebih besar, atau bahkan BigInteger.
Dalam suatu aplikasi kami ingin mentransfer Karakter Bahasa Inggris, Karakter Persia dan Simbol yang terlihat melalui SMS. Seperti yang Anda lihat ada 32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127nilai yang mungkin, yang dapat direpresentasikan dengan 7 bit.
Kami mengkonversi setiap karakter UTF-8 (16 bit) menjadi 7 bit, dan mendapatkan lebih dari rasio kompresi 56%. Jadi kami dapat mengirim teks dengan panjang dua kali lipat dalam jumlah SMS yang sama. (Entah bagaimana hal yang sama terjadi di sini).
Anda telah menyandikan karakter sebagai nilai 5-bit dan mengemas 11 di antaranya menjadi panjang 64 bit.
(packedValues >> 5*i) & 31 adalah nilai enkode ke-i dengan rentang 0-31.
Bagian yang sulit, seperti yang Anda katakan, adalah pengkodean ruang. Huruf bahasa Inggris kecil menempati kisaran yang berdekatan 97-122 di Unicode (dan ascii, dan sebagian besar penyandian lainnya), tetapi ruangnya 32.
Untuk mengatasinya, Anda menggunakan aritmatika. ((x+64)%95)+32hampir sama dengan x + 96(perhatikan bagaimana bitwise OR setara dengan penambahan, dalam kasus ini), tetapi ketika x = 31, kita dapatkan 32.
Anda harus menjelaskan apa yang Anda lakukan, alih-alih memposting teka
Aleksandr Dubinsky
1
Saya sarankan Anda menginvestasikan beberapa upaya dalam menemukan situs (mungkin beberapa Beta StackExchange?) Di mana kontribusi teka-teki yang menyenangkan diterima. Stack Overflow adalah situs tanya jawab dengan fokus ketat.
Marko Topolnik
1
@MarkoTopolnik Saya akan benci hidup di dunia di mana semua aturan atau fokus diberlakukan dengan ketat sehingga tidak pernah mengizinkan pengecualian. Belum lagi ada begitu banyak pengecualian pada SO.
גלעד ברקן
1
Saya juga akan melakukannya, tetapi SO adalah dunia yang luar biasa besarnya. Tentu ada pengecualian bahkan di sini, tetapi mereka tidak diterima .
Marko Topolnik
1
15 lainnya membagikan sentimen Alexandr. Dan Anda benar dalam menunjukkan bahwa pertanyaan itu sendiri tidak pantas untuk SO, seperti yang dikomentari di bawahnya.
Marko Topolnik
3
Tanpa Oracletag, sulit untuk melihat pertanyaan ini. Karunia aktif membawaku ke sini. Saya berharap pertanyaannya memiliki tag teknologi lain yang relevan juga :-(
Saya kebanyakan bekerja dengan Oracle database, jadi saya akan menggunakan beberapa Oraclepengetahuan untuk menafsirkan dan menjelaskan :-)
Mari kita konversi nomornya 4946144450195624menjadi binary. Untuk itu saya menggunakan functiondec2bin kecil bernama 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>
Mari kita gunakan fungsi untuk mendapatkan nilai biner -
SQL> SELECT dec2bin(4946144450195624) FROM dual;
DEC2BIN(4946144450195624)--------------------------------------------------------------------------------10001100100100111110111111110111101100011000010101000
SQL>
Sekarang tangkapannya adalah 5-bitkonversi. Mulai pengelompokan dari kanan ke kiri dengan 5 digit di setiap grup. Kita mendapatkan :-
Kami akhirnya akan dibiarkan dengan hanya 3 digit di ujungnya di kanan. Karena, kami memiliki total 53 digit dalam konversi biner.
SQL> SELECT LENGTH(dec2bin(4946144450195624)) FROM dual;
LENGTH(DEC2BIN(4946144450195624))---------------------------------53
SQL>
hello worldtotal memiliki 11 karakter (termasuk spasi), jadi kita perlu menambahkan 2 bit ke grup terakhir yang tersisa hanya 3 bit setelah pengelompokan.
Sekarang, kita perlu mengubahnya menjadi nilai ascii 7-bit. Untuk karakter itu mudah, kita hanya perlu mengatur bit 6 dan 7. Tambahkan 11ke setiap grup 5-bit di atas ke kiri.
Mari kita menafsirkan nilai-nilai biner, saya akan gunakan 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>
Mari kita lihat setiap nilai biner -
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>
Mari kita lihat karakter apa mereka: -
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>
Jadi, apa yang kita dapatkan di output?
dlrow ⌂ olleh
Itu hello⌂world secara terbalik. Satu-satunya masalah adalah ruang . Dan alasannya dijelaskan dengan baik oleh @ higuaro dalam jawabannya. Jujur saya tidak bisa menafsirkan masalah ruang angkasa pada upaya pertama, sampai saya melihat penjelasan yang diberikan dalam jawabannya.
Jawaban:
Jumlahnya
4946144450195624
pas 64 bit, representasi binernya adalah:Program mendekode karakter untuk setiap grup 5-bit, dari kanan ke kiri
Kodifikasi 5-bit
Untuk 5 bit, dimungkinkan mewakili 2⁵ = 32 karakter. Alfabet bahasa Inggris berisi 26 huruf, ini menyisakan ruang untuk 32 - 26 = 6 simbol terpisah dari huruf. Dengan skema kodifikasi ini Anda dapat memiliki semua 26 (satu huruf) huruf bahasa Inggris dan 6 simbol (menjadi spasi di antara mereka).
Deskripsi algoritma
The
>>= 5
dalam for-loop melompat dari grup ke grup, maka grup 5-bit terisolasi DAN nomor dengan topeng31₁₀ = 11111₂
dalam kalimatl & 31
Sekarang kode memetakan nilai 5-bit ke karakter ascii 7-bit yang sesuai. Ini adalah bagian yang sulit, periksa representasi biner untuk huruf alfabet huruf kecil dalam tabel berikut:
Di sini Anda dapat melihat bahwa karakter ascii yang ingin kami petakan dimulai dengan set bit ke-7 dan ke-6 (
11xxxxx₂
) (kecuali untuk ruang, yang hanya memiliki bit ke-6), Anda dapatOR
menggunakan kodifikasi 5-bit dengan96
(96₁₀ = 1100000₂
) dan itu seharusnya cukup untuk melakukan pemetaan, tetapi itu tidak akan berhasil untuk ruang (ruang sialan!)Sekarang kita tahu bahwa perhatian khusus harus diambil untuk memproses ruang pada saat yang sama dengan karakter lain. Untuk mencapai ini, kode mengaktifkan bit ke-7 (tetapi bukan ke-6) pada grup 5-bit yang diekstraksi dengan OR 64
64₁₀ = 1000000₂
(l & 31 | 64
).Sejauh ini kelompok 5-bit berbentuk:
10xxxxx₂
(ruang akan1011111₂ = 95₁₀
). Jika kita dapat memetakan ruang untuk0
menghapus nilai-nilai lain, maka kita dapat mengaktifkan bit ke-6 dan itu saja. Inilahmod 95
bagian yang harus dimainkan, space1011111₂ = 95₁₀
, menggunakan operasi mod,(l & 31 | 64) % 95)
hanya ruang yang kembali0
, dan setelah ini, kode menghidupkan bit ke-6 dengan menambahkan32₁₀ = 100000₂
ke hasil sebelumnya,((l & 31 | 64) % 95) + 32)
mengubah nilai 5-bit menjadi ascii yang valid karakterKode berikut melakukan proses invers, diberi string huruf kecil (maks 12 karakter), mengembalikan nilai panjang 64 bit yang dapat digunakan dengan kode OP:
sumber
Menambahkan beberapa nilai ke jawaban di atas. Script groovy berikut mencetak nilai-nilai perantara.
Ini dia
sumber
Menarik!
Karakter ASCII standar yang terlihat berada dalam kisaran 32 hingga 127.
Itu sebabnya Anda melihat 32, dan 95 (127 - 32) di sana.
Sebenarnya setiap karakter dipetakan ke 5 bit di sini, (Anda dapat menemukan apa kombinasi 5 bit untuk setiap karakter), dan kemudian semua bit digabungkan untuk membentuk angka yang besar.
Panjang positif adalah angka 63 bit, cukup besar untuk menampung bentuk terenkripsi 12 karakter. Jadi cukup besar untuk menampung
Hello word
, tetapi untuk teks yang lebih besar Anda harus menggunakan angka yang lebih besar, atau bahkan BigInteger.Dalam suatu aplikasi kami ingin mentransfer Karakter Bahasa Inggris, Karakter Persia dan Simbol yang terlihat melalui SMS. Seperti yang Anda lihat ada
32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127
nilai yang mungkin, yang dapat direpresentasikan dengan 7 bit.Kami mengkonversi setiap karakter UTF-8 (16 bit) menjadi 7 bit, dan mendapatkan lebih dari rasio kompresi 56%. Jadi kami dapat mengirim teks dengan panjang dua kali lipat dalam jumlah SMS yang sama. (Entah bagaimana hal yang sama terjadi di sini).
sumber
| 64
dilakukan.Anda mendapatkan hasil yang merupakan
char
representasi dari nilai di bawah inisumber
Anda telah menyandikan karakter sebagai nilai 5-bit dan mengemas 11 di antaranya menjadi panjang 64 bit.
(packedValues >> 5*i) & 31
adalah nilai enkode ke-i dengan rentang 0-31.Bagian yang sulit, seperti yang Anda katakan, adalah pengkodean ruang. Huruf bahasa Inggris kecil menempati kisaran yang berdekatan 97-122 di Unicode (dan ascii, dan sebagian besar penyandian lainnya), tetapi ruangnya 32.
Untuk mengatasinya, Anda menggunakan aritmatika.
((x+64)%95)+32
hampir sama denganx + 96
(perhatikan bagaimana bitwise OR setara dengan penambahan, dalam kasus ini), tetapi ketika x = 31, kita dapatkan32
.sumber
Mencetak "hello world" untuk alasan yang sama seperti ini:
tetapi untuk alasan yang agak berbeda dari ini:
sumber
Tanpa
Oracle
tag, sulit untuk melihat pertanyaan ini. Karunia aktif membawaku ke sini. Saya berharap pertanyaannya memiliki tag teknologi lain yang relevan juga :-(Saya kebanyakan bekerja dengan
Oracle database
, jadi saya akan menggunakan beberapaOracle
pengetahuan untuk menafsirkan dan menjelaskan :-)Mari kita konversi nomornya
4946144450195624
menjadibinary
. Untuk itu saya menggunakanfunction
dec2bin kecil bernama decimal-to-binary .Mari kita gunakan fungsi untuk mendapatkan nilai biner -
Sekarang tangkapannya adalah
5-bit
konversi. Mulai pengelompokan dari kanan ke kiri dengan 5 digit di setiap grup. Kita mendapatkan :-Kami akhirnya akan dibiarkan dengan hanya 3 digit di ujungnya di kanan. Karena, kami memiliki total 53 digit dalam konversi biner.
hello world
total memiliki 11 karakter (termasuk spasi), jadi kita perlu menambahkan 2 bit ke grup terakhir yang tersisa hanya 3 bit setelah pengelompokan.Jadi, sekarang kita memiliki: -
Sekarang, kita perlu mengubahnya menjadi nilai ascii 7-bit. Untuk karakter itu mudah, kita hanya perlu mengatur bit 6 dan 7. Tambahkan
11
ke setiap grup 5-bit di atas ke kiri.Itu memberi: -
Mari kita menafsirkan nilai-nilai biner, saya akan gunakan
binary to decimal conversion function
.Mari kita lihat setiap nilai biner -
Mari kita lihat karakter apa mereka: -
Jadi, apa yang kita dapatkan di output?
dlrow ⌂ olleh
Itu hello⌂world secara terbalik. Satu-satunya masalah adalah ruang . Dan alasannya dijelaskan dengan baik oleh @ higuaro dalam jawabannya. Jujur saya tidak bisa menafsirkan masalah ruang angkasa pada upaya pertama, sampai saya melihat penjelasan yang diberikan dalam jawabannya.
sumber
Saya menemukan kode sedikit lebih mudah dimengerti ketika diterjemahkan ke dalam PHP, sebagai berikut:
Lihat kode langsung
sumber
out.println ((char) (((l & 31 | 64)% 95) + 32/1002439 * 1002439));
Untuk membuatnya tutup: 3
sumber