[解決済み] hello world "と表示されるのはなぜですか?
質問
こんな変なものを発見しました。
for (long l = 4946144450195624l; l > 0; l >>= 5)
System.out.print((char) (((l & 31 | 64) % 95) + 32));
出力します。
hello world
どのように動作するのでしょうか?
どのように解決するのですか?
番号
4946144450195624
は64ビットに適合し、そのバイナリ表現は
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
はグループからグループへジャンプし、5ビットのグループが分離され、その番号とマスク
31₁₀ = 11111₂
文中
l & 31
ここで、コードは5ビットの値を対応する7ビットのアスキー文字にマッピングします。ここが難しいところですが、小文字の2進数表現を確認してください。 のアルファベットの文字があります。
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
ここで、マッピングしたいアスキー文字は、7番目と6番目のビットセットで始まっていることがわかります (
11xxxxx₂
) (6ビット目しかオンになっていないスペースを除く)であれば、次のようになります。
OR
5ビット
でのコード化
96
(
96₁₀ = 1100000₂
しかし、これではスペースに対応できません(スペースがない!)。
さて、スペースを他の文字と同時に処理するためには、特別な注意が必要であることがわかりました。そのために、このコードでは、7番目のビットをオンにして(6番目はオンにしていない)、他の文字を処理します。
抽出された5ビット群をOR64で表現したもの
64₁₀ = 1000000₂
(
l & 31 | 64
).
ここまでが5ビット群の形です。
10xxxxx₂
(スペースは
1011111₂ = 95₁₀
).
もし、空間を
0
他の値に影響を与えないように、6番目のビットをオンにすれば、それで済むはずです。
以下は
mod 95
の部分は、スペースが
1011111₂ = 95₁₀
を使用すると、MOD
操作
(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文字)を与えると、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);
}
}
関連
-
Java のエラーです。未解決のコンパイル問題 解決方法
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] JavaでStringをintに変換するにはどうしたらいいですか?
-
[解決済み] バイトを文字列に変換する
-
[解決済み] ランダムな文字列を使用するこのコードは、なぜ "hello world" と表示されるのですか?
-
[解決済み] java.lang.UnsupportedClassVersionError を修正する方法。サポートされていないメジャー.マイナーバージョン
-
[解決済み] 特定のUnicode文字を含むコメントでのJavaコードの実行が許可されているのはなぜですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
java.util.NoSuchElementException 原因解析と解決方法
-
SpringBootApplication を型解決できない。
-
Dateが型に解決できない問題を解決する
-
JavaMailのメール送信が失敗するケースとその説明の分析
-
Eclipseプロンプトを実行する java仮想マシンを使用しない
-
スレッド "main" での例外 java.lang.ArrayIndexOutOfBoundsException: 1
-
自動配線された依存性のインジェクションに失敗しました。
-
Error: java.lang.NoClassDefFoundError: クラス XXXX を初期化できませんでした
-
SocketTimeoutExceptionの解決方法です。読み込みがタイムアウトした
-
Java(1)仕上げの基本概念+eclipseのインストール構成