web-dev-qa-db-ja.com

プログラミング時に他の基数を使用する理由

私の同僚と私は、だれもが10以外のベースで数値をプログラムするために彼らの方法から出て行く理由を理解することに心を傾けてきました。

おそらく、作業している正しいベースに変数を配置することで、より長い方程式を最適化できると提案しました(たとえば、残りがなく、5のセットしかなく、ベース5を使用できる場合)。それが本当なら。

何かご意見は?

35
JMD

基数10以外のコードで数値を記述する通常の理由は、ビットをいじるからです。

Cで例を選択するには(Cが何かに適している場合は、ビットをいじるのに適しているため)、低レベルの形式がバイトに2ビットと6ビットの数値をエンコードするとします。xx yyyyyy

main() {
    unsigned char codevalue = 0x94; // 10 010100
    printf("x=%d, y=%d\n", (codevalue & 0xc0) >> 6, (codevalue & 0x3f));
}

作り出す

x=2, y=20

このような状況では、定数を16進数で書く方が10進数で書くよりも混乱が少なくなります。16進数の1桁は4ビット(半バイト、1つの「ニブル」)と2〜1バイトに対応しているためです。数値0x3fは、すべてのビットを低ニブルに設定し、2ビットを高ニブルに設定します。

2行目を8進数で書くこともできます。

printf("x=%d, y=%d\n", (codevalue & 0300) >> 6, (codevalue & 077));

ここでは、各桁が3ビットのブロックに対応しています。それを考える方が簡単だと思う人もいますが、最近では珍しいと思います。

59
Norman Gray

異なるベースを使用する主な理由は、ビットを気にするときです。

読みやすくなります

int mask=0xFF;
byte bottom_byte = value & mask;

より

int mask=255;
byte bottom_byte = value & mask;

またはもっと複雑なイメージ

int mask=0xFF00FF00;
int top_bytes_by_Word = value & mask;

に比べ

int mask=4278255360; //can you say magic number!? 
int top_bytes_by_Word = value & mask;

Hexは基本的にバイナリのよりコンパクトな形式であるため、hexの例の意図がここで非常に明確になっています...対照的に、base-10(使用するもの)はバイナリにほとんど対応していません。

0xFF = b11111111 = 255
0xFFFF = b1111111111111111 = 65536
0xF0F0 = b1111000011110000 = 61680

一部の言語で使用できる他のベースもあります。 2進数、16進数、10進数以外の基数の使用はほとんどありません。奇妙な人々はまだ8進数を使用しますが、これは正気なプログラムで見られる最も難解なものです。

45
Earlz

おそらくご存知のとおり、コンピューターはバイナリに基づいています。これはベース2です。

基数2と4、8と16(および同様の2の倍数)の間で変換するのは簡単であり、この変換をソースコードに保持すると理由を考えると、数値の操作がはるかに簡単になります。

アセンブリやCなどの低レベル言語の場合、これは直接プロセッサ演算(除算や乗算のビットシフトなど)に変換できます。つまり、これらの数値の基数を使用すると、コードがはるかに高速になります。

さらに、すべての演算が数値演算であるわけではありません。ビットを直接いじる必要があるビットマップがあります。基数2またはその倍数の1つを使用すると、演算がはるかに簡単になります。

詳細については、 Code by Charles Petzold をお読みになることをお勧めします。

8
Oded

おそらく、 base 12 system。 を使用する古代文明の経済をシミュレートするゲームを書いている場合は、

6
MetaGuru

高度に専門化されたプログラム以外では、10、16、2以外のベースを使用することはほとんどありません。

基数16(16進数)は、バイトの全範囲(0-255)を2桁(0x00-0xFF)で表すことができるので便利です。これにより、生の16進ダンプまたはバイナリデータの処理がはるかに簡単になります。 16進数は、ビット単位の演算子でビットマスクを使用する場合にも役立ちます。これは、2桁からバイトへの対応が読みやすくなるためです。

まれに、ベース2(バイナリ)をビット単位の演算で使用することもできますが、多くのプログラミング言語はベース2リテラルをサポートしておらず、16進数の方がはるかに簡潔で読みやすくなっています。

UNIXファイルのアクセス許可のため、Base-8(8進数)も使用されることがあります。それ以外では、高度に専門化された数学コンテキスト以外で10以外のベースを使用することはほとんどありません。

4
Charles Salvia

他のベースを使用する最も一般的な有効な理由は、ベース2への変換の容易さに関係しています。8または16の短いテーブルを記憶することにより、計算機を使用せずに、ベース8またはベース16の数値をバイナリに変換することは簡単です。数:

 0000 0     0001 1     0010 2     0011 3
 0100 4     0101 5     0110 6     0111 7
 1000 8     1001 9     1010 A     1011 B
 1100 C     1101 D     1110 E     1111 F

これにより、複数の可能性が開かれます。

  • 数値が意味のある2進数の構成を表す場合、コンピューターがなくても個々のコンポーネントを判別できます。たとえば、24ビットの数値がRGBの色を表す場合、0xFF00FFマゼンタ (赤+青)であることは簡単です。 16711935が提示されると、タスクははるかに困難になります
  • 数値がビットマスクを表す場合、より長い2進数ではなく、コンパクトな16進数として書き留める方が現実的です。
  • 特定のアーキテクチャは、8進数として出力されたときにバイナリコードを読みやすくするために邪魔になりました。 PDP-11はそのようなシステムの1つでした。最上位ビットを使用すると、8ビットの操作と16ビットの操作を区別できます。最後の2つの8進グループを使用すると、操作に関連する2つのレジスターなどを指定できます。逆アセンブラなしでPDP-11バイナリコードを画面から読み取ることができる人を何人か知っていましたが、マシンコードを8進法で印刷する必要がありました。
3
dasblinkenlight

コンピュータ(より正確にはコンパイラ)は、ソースコードで使用する基数をまったく気にしません。最も一般的に使用されるプログラミング言語は、ベース8(8進数)、10(10進数)、16(16進数)を直接サポートします。 2進数(2進数)を直接サポートしているものもあります。特殊言語は、他の数値ベースもサポートする場合があります。 (「直接サポート」とは、ソースコード自体のビットシフト、乗算、除算などの数学的トリックに頼らずに、その基数に数値を入力できることを意味します。たとえば、Cは0xでbase-16を直接サポートします。番号の接頭辞と0123456789ABCDEFの通常の16進数字セットです。このようなトリックは、コンテキストで数値を理解しやすくするのに役立ちますが、それらを使わずに同じ数を表現できる限り、そうするかどうかは、便利です。)

しかし結局、それは重要ではありません。次のようなステートメントがあるとします。

int n = 10;

その目的は、整数変数を作成し、それを10進数10で初期化することです。コンピューターには何が表示されますか?

i  n  t     n     =     1  0  ;
69 6e 74 20 6e 20 3d 20 31 30 3b (ASCII, hex)

コンパイラはこれをトークン化し、intという名前のn型の変数を宣言していることを認識し、それにいくつかの初期値を割り当てます。しかし、その値は何ですか?

コンピューターにとって、バイトの順序と配置の問題を無視すると、変数の初期値の入力は0x31 0x30です。これは、初期値が0x3130(ベース10では12592)であることを意味しますか?もちろん違います。言語パーサーは、使用される文字エンコーディングでファイルを読み取り続ける必要があるため、10の後にステートメントターミネータが続きます。この言語では10を想定しているので、これは(逆方向に)「0 1、1 10、終わり」と読みます。つまり、10進数の10の値です。

16進数で値を指定し、言語が0xを使用して次の値が16進数であることを指定すると、次のようになります。

i  n  t     n     =     0  x  1  0  ;
69 6e 74 20 6e 20 3d 20 30 78 31 30 3b (ASCII, hex)

コンパイラーは0x(0x30 0x78)を認識し、それをbase-16プレフィックスとして認識します。そのため、その後に続く有効なbase-16番号を探します。ステートメントターミネータまでは、10を読み取ります。これは、0の「1」、1の「16」に変換されます。これは、基数10で16、基数2で00010000になります。

どちらの場合も、単純化のために最適化を無視して、コンパイラーはintタイプの変数の値を保持するのに十分なストレージを割り当て、ソースコードから読み取った値をある種の一時保持変数に配置します。次に、(おそらくかなり後で)結果のバイナリ値をオブジェクトコードファイルに書き込みます。

ご覧のとおり、ソースコードに数値を書き込む方法はまったく重要ではありません。それはかもしれませんコンパイル時間に非常にわずかな影響がありますが、私は(繰り返しになりますが、オペレーティングシステムによるディスクキャッシュなどの最適化を無視して)ディスクの回転プラッタの周りのランダムな乱流、ディスクアクセス時間、データバスの衝突などの影響がはるかに大きいと想像してください。

結論:心配する必要はありません。選択したプログラミング言語がサポートするベースで数値を記述します。これにより、数値の使用方法や読み取り方法がわかります。この回答を読むのにはるかに多くの時間を費やしましたが、ソースコードで使用する数値ベースを賢くすることで、コンパイル時間を回復することはありません。 ;)

2
a CVn

金融業界には、 識別子スキーム があり、これは事実上36基です。 0〜35の数字を表すために、0〜9の数字とB〜Zの文字を使用しています。不快な名前が生成されないように、母音をスキップします。

しかし、それは完璧ではありません。ある不幸な会社がID B000BZ

1

理由#1:回路レベルのすべての数値がbase-2で表されるため(電気スイッチがオンまたはオフ)。理由#2:実際の回路よりも1レベル高いため、ビットはバイトにグループ化され、バイトは2つの16進数字として簡単に表すことができます。バイト。

したがって、これらのレベルで作業している場合(または管理された環境でそれらを概算している場合)、10進数よりも2進数または16進数で作業する方が簡単です。これを行う状況はさまざまですが、基本的な計算だけが必要な状況ではありません。

1
KeithS

基数16(16進数)の数値が頻繁に使用される1つの領域は、特にWebでHTML/CSSを使用する場合の色の指定です。私たちがデジタルディスプレイで使用する色は、3つの「ベース」カラー(RGB-赤、緑、青)の3つの強度値の組み合わせを使用して指定され、これらをブレンドして、1600万個の表示可能な色(24ビットカラーを使用)を作成します。 )。

たとえば、16進数の完全な強度の緑は、10進数で0x00ff00および65280になります。ここで、頭の中で赤と青の部分が等しい色を「手動で」混合して、たとえば半分の強度で、素敵な紫を作成しようとしていると想像してください。16進数では、これは単に0x800080と書かれ、10進数の値はこれは8388736になります。グレーのシェードを操作するとさらに簡単になります。50%グレーは0x808080(16進数)および8421504(10進数)、75%は0xC0C0C0および12632256などです。オン。

16進数の使用ははるかに直感的であり、この色の使用に慣れている人は、16進数の値を見ればすぐに色を「推測」できます。また、同じ色を複数回使用する必要がある場合にも、エラーが発生しにくくなります(通常そうです)。

任意のWebページ(特にCSS)をチェックして、16進数の使用法が狂っているかどうかを確認してください:D

注:CSSでは、16進値は#接頭辞を使用して記述されます。たとえば、緑の場合は#00ff00であり、緑の場合は#0f0のように3桁に短縮されることもあります。

1
free3dom

だれもが10以外のベースで数値をプログラムするために邪魔になる理由.

まだ表示されていない理由をいくつか次に示します...

x00-一部のOSおよびハードウェアデバイスのAPIは、引数が16進数/バイナリであると想定しています。このようなAPIをコーディングする場合、異なるベース間で変換する代わりに、APIが期待するのと同じ形式で数値を使用する方が簡単です。たとえば、メッセージの終わりバイトをサーバーに送信したり、メッセージを送信して通信チャネルへの接続を閉じたりします。

x01-著作権記号(\ u00a9)など、特定のキーボードでは使用できない文字をアプリケーションで表すことができます。

x02-特に、ソースコード/ファイルがローカル設定が異なる開発者間で移動された場合に、いくつかの定数/リテラル​​を異なるカルチャ設定で(視覚的に)保持します。

x03-コードがわかりにくく複雑に見えるようにするために-C#は8進定数をサポートしていないというのは良いことです。

1
NoChance

重要な問題は、1つのWordのコンピュータサイズを適切に表現することです。 6502は8ビットプロセッサでした。 4004は4ビットプロセッサでした。

4ビットまたは8ビットの数値を扱う場合、うまく機能します。 4ビットの数値は、単一の16進文字です。 8ビットの数値(1バイト)は2桁の16進数です。 2サイズのWordの能力を持つシステムは、今日一般的に見られる標準です(16ビット、32ビット、64ビット)。これらはすべて、16進数として表現するために4で割ります。

Octal (基数8)は、Wordサイズが12、24、または36であるシステムで使用されていました。PDP8、IBMメインフレーム、およびICL 1900日数は、これらを使用しました。これらの単語は、16進数の限られた範囲ではなく、オクテットを使用してより簡単に表現されました(そうです、それらも4に分割されます)。

どうやら、base 8の番号付けを使用することで、コストも削減されました。 BCDで12ビットを表す場合、最初の桁は0〜4のみですが、2、3、4番目は0〜9になります。これが16進数として行われた場合、1つは3つの16進数文字を持ちますが、それぞれに16の可能な値があります。 0-9(BCDの追加ロジックあり)または0-F(16進数)を持つものよりも0-7だけの nixieチューブ を作成する方が安価でした。

現在でも、UNIXファイルのアクセス許可(755、644)が8進数で表示されます。所有者、グループ、およびワールドにはそれぞれ、アクセス許可を表す3ビットがあります。


数学の世界では、時々、異なる基底を使って奇妙なことをします。たとえば、 project euler 396 ...からの弱いGoodsteinシーケンス、または palindromic numbers を使用したより簡単なシーケンス。基数[〜#〜] n [〜#〜]には、複数の数であるという数のプロパティがあります。のN-1は、の倍数になるまで、その桁の合計を持ちますN-1。さらに、N-1が完全な正方形である場合、このプロパティはsqrt(N-1)。これは、特定の数学的問題にいくつかの用途があります。

1
user40980

正直なところ、これは何らかの理由で多指症で11本の指を持っているか、つま先で数えるのが好きなので、ベース20で作業するのは正直あなた次第です。ただし、普遍性のトピックでは、日常的にビットとバイトを処理する必要があるほとんどの人が、ベース19でビット操作を実行しているものを取得した場合、実際にチェックされます。

ベースxの理由

基数10-10桁の数字があるため、すべてのもののモデル(足は奇妙で臭いので、使用しません)。

ベース2-コンピュータはこれをビット(オン/オフ)に使用します。これは、ゲート/トランジスタ/コンデンサによって伝播される読み取り可能な電圧レベルに関連しています。

ベース8-古い、コンピューターが超巨大でなかったとき(またはスペースが賢明だったとき)は、これは何かに適していました(私は少し好きではありません)

ベース16-ビット操作のためにバイトの上位および下位ニブルを表示するのに適しています。これは、embedded/fpga/hardwareの世界では非常に便利です。

コンピュータの通常のベース

好みに合わせて、私に与えられた16進数のRGB値で色がどの程度「オン」であるかを正確に伝えることができます。これは、ハードウェアで単一のintで表すことができ、いくつかのシフトで私に返すことができます簡単な、1つの複雑な色= 1つのデータポイントは、限られたメモリで大規模な画像処理を行うのに適しています。それをベース10の表現と比較すると、それらをすべて追加して数値に格納できますが、どの数値か、またはおそらくRは時間10000、Gは100、Bは独自のスペースです。これは多くの数学演算です、通常、乗算はシフトよりもサイクルがかかるため、次のデータピースは、最後のピースが処理される前にすでにキューに入っています。

場合によっては、2、8、16のベースで作業する方が良い場合があります。ほとんどのマシンでは、2による乗算はビットシフトに過ぎず、2による除算と同じように非常に高速です。

ビットいじりのアイデアをさらに詳しく説明します。組み込み環境で作業しているときに、ライトの配列、スイッチ、またはその他のレジスターにマップされたアイテムにアクセスする必要が何度もありました。

この場合、char、byte、またはint全体を各スイッチに割り当てることは非効率的で愚かなことです。スイッチまたはライトには2つの位置があります-オンとオフ-最大256の位置、つまり2 ^ 16の何かを割り当てるのはなぜですか位置など。アレイ内の各ライトは、1つのワード/レジスタに8または16または32または64または128(データ型の幅)に適合する1ビットである可能性があります。スペース効率が必要であり、むしろ歓迎されています。

RGBデータ、多くの信号データ(GPS、オーディオ、ASCIIなど)の処理などのプログラミングで、ベース2 ^ nの何かを使用することは、16進、2進、8進ではるかに簡単です。提示されている内容とその操作方法をより簡単に識別します。

ストレンジベースを使用

コーディングしない限り、効率はありません。基本11が必要な場合は、そのデータ型を設定し、演算子をオーバーロードしてユーザーへの表現を処理する必要があります。 5つのアイテムを保持するシステムで、5つのアイテムの倍数を保持するだけで5つのアイテムの数学に変換する必要がある理由はわかりません。さらに、ベース271のコードを書くことに決めた人がそれをうまく文書化するように祈るか、すべてのアイテムが271の倍数であるため、ベース271を作成する価値があるよりも多くの時間を費やすことができます。

0
Jeff Langemeier

昔のコンピューターの時代には、0〜9の数字を表示できるディスプレイがいくつかありましたが、A〜Fはまだありませんでした。

http://ad7zj.net/kd7lmo/images/ground_nixie_front.jpg はそのような例の1つです...

Octalはこれらのディスプレイに非常によく適合し、2進数や10進数よりも簡単でした。

0

他のすべての回答で、代替ベースのコンピューティングにおける2つの非常に一般的な使用法について言及していないことに驚いています。

  1. エンコーディング:たとえばBase64エンコーディングは非常に一般的です。エンコードでは、一連のバイトを大きなバイナリ(base-2)数として解釈し、その数をASCII桁で表されるBase64数に変換します。
  2. 圧縮:表現を短くするために、2進数、10進数、または16進数をより大きな基数で表すことが望ましい場合がよくあります。たとえば、bit.lyのようなすべてのビット短縮機能がこれを行っています。または、URLで使用するためにGUIDを短縮するためにそれを行うかもしれません。

    - 821F6321-881B-4492-8F84-942186DF059B (base-16 guid) 
    becomes
    - RRIDHW463YD8YXX7MIDI (base-36)
    - 3UFmaWDjj9lifYyuT0 (base-62)
    

一部のアルゴリズムでは、base 2は他の何よりも意味があります。たとえば、2進ツリーまたは10進ツリーをトラバースする関数を作成しますか?

しかし、より頻繁には、base 2が使用されます。これは、コンピューターがほとんど普遍的にそれらの数を表す方法だからです。この意味は:

  • 基数2:では、多くの操作がより効率的です。
    • 乗算、除算、2のべき乗は、一般的な除算よりもはるかに高速です。
    • フラグと小さな値は、より大きな数の2進数として、より効率的に格納、取得、および操作できます。
  • データファイルとネットワークデータストリームの読み取り、書き込み、操作を行う操作は、それらが2進数として表されるという事実を直接処理する必要があります。

また、2でも10でもない奇数のベースを本質的に必要とするまれなアプリケーションが常に存在します。

0
comingstorm