[解決済み] Javaで整数のlog base 2を計算する方法は?
質問
以下の関数を使って、整数のlog base 2を計算しています。
public static int log2(int n){
if(n <= 0) throw new IllegalArgumentException();
return 31 - Integer.numberOfLeadingZeros(n);
}
最適なパフォーマンスを発揮するか?
そのためのJ2SE API関数をご存知の方はいらっしゃいませんか?
UPD1 意外なことに、浮動小数点演算は整数演算より速いようです。
UPD2 ご指摘を受け、より詳細な調査を行うことになりました。
UPD3 私の整数演算関数は Math.log(n)/Math.log(2) より10倍高速です。
どのように解決するのですか?
整数演算の補助に浮動小数点を使おうと考えている人は、注意が必要です。
私は普段、可能な限りFPの計算をしないようにしています。
浮動小数点演算は厳密ではありません。何が起こるかを確実に知ることはできません。
(int)(Math.log(65536)/Math.log(2))
と評価されます。 例えば
Math.ceil(Math.log(1<<29) / Math.log(2))
は私のPCでは30ですが、数学的には正確に29になるはずです。xの値で
(int)(Math.log(x)/Math.log(2))
は失敗しますが(32個の "dangerous" 値しかないため)、どのPCでも同じように動作するということではありません。
ここでの通常のトリックは、丸めるときに "epsilon" を使うことです。例えば
(int)(Math.log(x)/Math.log(2)+1e-10)
は失敗しないはずです。この "epsilon" を選択するのは些細な作業ではありません。
より一般的なタスクを使って、より多くのデモンストレーションを行います。
int log(int x, int base)
:
テスト用のコードです。
static int pow(int base, int power) {
int result = 1;
for (int i = 0; i < power; i++)
result *= base;
return result;
}
private static void test(int base, int pow) {
int x = pow(base, pow);
if (pow != log(x, base))
System.out.println(String.format("error at %d^%d", base, pow));
if(pow!=0 && (pow-1) != log(x-1, base))
System.out.println(String.format("error at %d^%d-1", base, pow));
}
public static void main(String[] args) {
for (int base = 2; base < 500; base++) {
int maxPow = (int) (Math.log(Integer.MAX_VALUE) / Math.log(base));
for (int pow = 0; pow <= maxPow; pow++) {
test(base, pow);
}
}
}
対数の最も素直な実装を用いれば
static int log(int x, int base)
{
return (int) (Math.log(x) / Math.log(base));
}
が表示されます。
error at 3^5
error at 3^10
error at 3^13
error at 3^15
error at 3^17
error at 9^5
error at 10^3
error at 10^6
error at 10^9
error at 11^7
error at 12^7
...
エラーを完全になくすには、1e-11と1e-14の間のイプシロンを追加する必要がありました。 テストする前にこのことを伝えることができたでしょうか? 間違いなく無理でした。
関連
-
エラーが報告されました。リソースの読み込みに失敗しました:サーバーは500(内部サーバーエラー)のステータスで応答しました。
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] JavaでStringをintに変換するにはどうしたらいいですか?
-
[解決済み] Javaで配列に特定の値が含まれているかどうかを判断するにはどうすればよいですか?
-
[解決済み] Java で、あるコンストラクタを別のコンストラクタから呼び出すにはどうすればよいですか?
-
[解決済み] Javaで配列を宣言し、初期化する方法は?
-
[解決済み] Javaの「for each」ループはどのように機能するのですか?
-
[解決済み] Eclipseを高速化する方法とは?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
スタイルが読み込まれず、ブラウザコンソールでエラーが報告される。リソースはスタイルシートとして解釈されますが、MIMEタイプtext/htmlで転送されます。
-
IllegalArgumentException この例外を解決する方法
-
eclipse アクセス制限です。タイプ 'xxx' は API ではありません(必須ライブラリ '' の制限)。
-
スキャナは、タイプに解決することはできません最もルーキー初心者の質問
-
eclipseにプロジェクトをインポートした後、Editorにmain typeが含まれない問題
-
eclipse の実行時に java 仮想マシンが見つからなかった
-
自動配線された依存性のインジェクションに失敗しました。
-
スレッド "main" で例外発生 java.net.BindException: アドレスは既に使用中です。NET_Bind
-
JSPで「リストが型解決できない!」の解決方法
-
maven プラグイン エラー プラグインの実行は、ライフサイクル構成ソリューションの対象外です。