東方算程譚

Oriental Code Talk ── επιστημηが与太をこく、弾幕とは無縁のシロモノ。

目次

Blog 利用状況

ニュース

著作とお薦めの品々は

著作とお薦めの品々は
東方熱帯林へ。

あわせて読みたい

わんくま

  1. 東京勉強会#2
    C++/CLI カクテル・レシピ
  2. 東京勉強会#3
    template vs. generics
  3. 大阪勉強会#6
    C++むかしばなし
  4. 東京勉強会#7
    C++むかしばなし
  5. 東京勉強会#8
    STL/CLRによるGeneric Programming
  6. TechEd 2007 @YOKOHAMA
    C++・C++/CLI・C# 適材適所
  7. 東京勉強会#14
    Making of BOF
  8. 東京勉強会#15
    状態遷移
  9. 名古屋勉強会#2
    WinUnit - お気楽お手軽UnitTest

CodeZine

  1. Cで実現する「ぷちオブジェクト指向」
  2. CUnitによるテスト駆動開発
  3. SQLiteで組み込みDB体験(2007年版)
  4. C++/CLIによるCライブラリの.NET化
  5. C# 1.1からC# 3.0まで~言語仕様の進化
  6. BoostでC++0xのライブラリ「TR1」を先取りしよう (1)
  7. BoostでC++0xのライブラリ「TR1」を先取りしよう (2)
  8. BoostでC++0xのライブラリ「TR1」を先取りしよう (3)
  9. BoostでC++0xのライブラリ「TR1」を先取りしよう (4)
  10. BoostでC++0xのライブラリ「TR1」を先取りしよう (5)
  11. C/C++に対応した、もうひとつのUnitTestFramework ─ WinUnit
  12. SQLiteで"おこづかいちょう"
  13. STL/CLRツアーガイド
  14. マージ・ソート : 巨大データのソート法
  15. ヒープソートのアルゴリズム
  16. C++0xの新機能「ラムダ式」を次期Visual Studioでいち早く試す
  17. .NETでマンデルブロ集合を描く
  18. .NETでマンデルブロ集合を描く(後日談)
  19. C++/CLI : とある文字列の相互変換(コンバージョン)
  20. インテルTBBによる選択ソートの高速化
  21. インテルTBB3.0 によるパイプライン処理
  22. Visual C++ 2010に追加されたSTLアルゴリズム
  23. Visual C++ 2010に追加されたSTLコンテナ「forward_list」
  24. shared_ptrによるObserverパターンの実装
  25. .NETでマンデルブロ集合を描く(番外編) ── OpenCLで超並列コンピューティング
  26. StateパターンでCSVを読む
  27. 状態遷移表からStateパターンを自動生成する
  28. 「ソートも、サーチも、あるんだよ」~標準C++ライブラリにみるアルゴリズムの面白さ
  29. インテルTBBの同期メカニズム
  30. なぜsetを使っちゃいけないの?
  31. WPFアプリケーションで腕試し ~C++でもWPFアプリを
  32. C++11 : スレッド・ライブラリひとめぐり
  33. Google製のC++ Unit Test Framework「Google Test」を使ってみる
  34. メールでデータベースを更新するココロミ
  35. Visitorパターンで遊んでみたよ
  36. Collection 2題:「WPFにバインドできる辞書」と「重複を許す検索set」
  37. Visual C++ 2012:stateless-lambdaとSQLiteのぷち拡張
  38. 「Visual C++ Compiler November 2012 CTP」で追加された6つの新機能

@IT

  1. Vista時代のVisual C++の流儀(前編)Vista到来。既存C/C++資産の.NET化を始めよう!
  2. Vista時代のVisual C++の流儀(中編)MFCから.NETへの実践的移行計画
  3. Vista時代のVisual C++の流儀(後編) STL/CLRによるDocument/Viewアーキテクチャ
  4. C++開発者のための単体テスト入門 第1回 C++開発者の皆さん。テスト、ちゃんとしていますか?
  5. C++開発者のための単体テスト入門 第2回 C++アプリケーションの効率的なテスト手法(CppUnit編)
  6. C++開発者のための単体テスト入門 第3回 C++アプリケーションの効率的なテスト手法(NUnit編)

AWARDS


Microsoft MVP
for Visual Developer - Visual C++


Wankuma MVP
for いぢわる C++


Nyantora MVP
for こくまろ中国茶

Xbox

Links

記事カテゴリ

書庫

日記カテゴリ

二進での桁数

ネタ元 → 脳内1%は秘密(笑)

「ある数値(integer)を二進数で表現したときに必要なbit数を簡単/高速に求めるには」

んー…
[1] 0になるまで2で割り続け、何回割ったかが二進数での桁数となります。
が、これだと最大32回の繰り返しが生じます(intが32bitなら)。
もっと簡単な方法があるかと言われますと...

R進数表現での桁数をnとすれば、R^n = 2^x とおくと n・logR = x・log2 なので
x = n・logR/log2 となります。 十進数すなわち R=10 とおけば、
x = n・log10/log2 ≒ 3.32・n
[2] よーするに十進での桁数を3.3倍(とちょっと)すると概ね二進での桁数となりますな。
ただしこの方法ではもっすご荒っぽい桁数しか得られません。
100も999も(3桁×3.3)二進で10桁だとゆー。

さらにこのやりかたでは十進で何桁かを求めにゃなりません。
よーするに0になるまで10で割り続け、何回割ったかを必要とします。
32bit-integerだと最大10回くらいは割らにゃならんのよね。

[3] 数学関数 Math.Log(double, double) で一気に求めることもできるけど、
単純にループ回すより速いとは思えないし...

で、いっちゃん手軽で速いのはやっぱ[1]になんでないかなーとか思います。
ざっくりした桁数でいいのなら
- 0になるまで4で割り、割った回数×2 とか
- 0になるまで8で割り、割った回数×3 とか
もアリかもです。

投稿日時 : 2007年7月24日 15:26

コメントを追加

# re: 二進での桁数 2007/07/24 15:41 NyaRuRu

http://msdn2.microsoft.com/en-us/library/fbxyd7zd(VS.80).aspx

# re: 二進での桁数 2007/07/24 15:51 επιστημη

そかintrinsicか、その発想はなかった ^^;
いっちゃん機械語に近いんで速いっちゃ速いっしょーね。

# re: 二進での桁数 2007/07/24 15:53 片桐

あ、ひんとー。
Logってやつがいるらしい。というのでぐぐってみたら、Log対数ってやつらしい。えっと、EXCELの式だと、=INT(LOG(A1,2)+1)がそれっぽいです。。
ということは、これをVB.NETで書ければいいのかしらん?

ちなみに、片桐は高校から数学を一切やってません(笑)
今更ながらちょっとずつ勉強中(^^;
サインとコサインとタンジェントはわかるようになったつもり……

# re: 二進での桁数 2007/07/24 16:01 片桐

うーーん……ということは、やっぱり2で割ってまわせってことなんかなぁ……。
NyaRuRuさんのリンク見るとC++だと便利な機能があるらしいことは理解。これをもってくる……ってそれも大変そう(遠い目)
とりあえず、今の所はToCharArrayのuboundにしといて、やっぱり、ということであれば2割にします(^^;

# re: 二進での桁数 2007/07/24 16:10 επιστημη

うん、「求めた桁数がいっこくらいなら多くてもいいよ」ならば"4で割った回数を求めて2倍"することで割る回数を半分にできるです。

> えっと、EXCELの式だと、=INT(LOG(A1,2)+1)がそれっぽいです。。

そーですね。「2を底とするlog値に1足して端折る」っす。
Math.Log(A1,2)+1 をint値にするわけだけど、
int→double, double→int 変換を伴うし
速度的にはどーよ? ってことで。

# re: 二進での桁数 2007/07/24 16:11 ぽぴ王子

とりあえず。

Dim wInt As Integer = Integer.Parse("0" & oBit.ToString)
Dim length As Integer = Convert.ToString(wInt, 2).Length

同じく数学嫌いだけど、最近林晴比古先生の「プログラマーの数学」を読み始めた王子がお伝えしました。

# re: 二進での桁数 2007/07/24 16:31 nagise

int val = 対象の数字
int digit = 1;

int t1 = 0xFF00 & val; // 1111 1111 0000 0000
int t2 = 0xF0F0 & val; // 1111 0000 1111 0000
int t3 = 0xCCCC & val; // 1100 1100 1100 1100
int t4 = 0xAAAA & val; // 1010 1010 1010 1010

digit += t1 ? 8 : 0;
digit += t2 ? 4 : 0;
digit += t3 ? 2 : 0;
digit += t4 ? 1 : 0;

てなロジックをうまく最適化してやると…

# re: 二進での桁数 2007/07/24 16:32 nagise

あ、駄目だ orz

# 脳内1%は秘密(笑) 2007/07/24 16:51 すいません、VB4しかやってないんです、VBAはやったけど(ぼそ)

脳内1%は秘密(笑)

# re: 二進での桁数 2007/07/24 17:03 nagise

int val = input;
int digit = 1;
if (0 < (val & 0xFFFF0000)) {
digit += 16;
val &= 0xFFFF0000;
}
if (0 < (val & 0xFF00FF00)) {
digit += 8;
val &= 0xFF00FF00;
}
if (0 < (val & 0xF0F0F0F0)) {
digit += 4;
val &= 0xF0F0F0F0;
}
if (0 < (val & 0xCCCCCCCC)) {
digit += 2;
val &= 0xCCCCCCCC;
}
if (0 < (val & 0xAAAAAAAA)) {
digit += 1;
}

一応、ちゃんと動く版。Javaだからifの()の中をbooleanにしているけど、Cだともうちょっとすっきりする。
この方針のアルゴリズムだと、むしろ、アセンブラのほうが処理が書きやすい気がする…。

# re: 二進での桁数 2007/07/24 21:21 2リットル

nagiseさんのすごいわー。

自分で実装するなら[1]かな。簡単だからw。
桁数がもっとおおくなったら2分探査をかけるぐらい。
下のはカンマ演算子を使ってみたかったので、書いてみました。反省はしていない。
binaryOrder(int x)
{
 int order = 0; // 2進の桁数
 while (order++, x >>= 1);
 return order;
}

# re: 二進での桁数 2007/07/24 21:27 2リットル

x < 0でハングするので修正。

getBinaryOrder(int x)
{
 int order = 0; // 2進の桁数
 unsigned int ux = x;
 while (order++, ux >>= 1);
 return order;
}

# re: 二進での桁数 2007/07/25 12:34 ゆーち

template<class T> T LogRound( T _Value )
{
const int bits = ( sizeof(_Value) * 8 );
T round = (T)1;

for( int i = 0; i < bits; i++, round <<= 1 )
{
if( _Value <= round )
{
return round;
}
}
return (T)0;
}
えー?C++じゃないんですかぁ?
バグってるし(w

# re: 二進での桁数 2007/07/26 21:22 Imabeppu

[1] はこんなのでも。

int foo(int n)
{
return (n == 0 ? 0 : 1 + foo(n >> 1));
}

タイトル
名前
URL
コメント