プログラミング時に他の数値ベースを使用する理由


35

同僚と私は、10以外のベースで数字をプログラムするために誰かが邪魔にならない理由を考え出すことに心を曲げてきました。

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

何かご意見は?


6
この質問を提起した具体的な例はありますか?コンピューターが理解しやすいため、ベース2またはベース16のものは明らかに利点があります。
-KDiTraglia

4
「ベースのプログラミング番号」とはどういう意味ですか?数字があります。期間。それらはいくつかのベースで内部的に表現されますが、それはほとんど問題ではなく算術規則を変更しません。

12
@JMD-モデレーターと協力して、2つのクロスポストの1つを削除し、1つをP.SEに配置してください。サイト間のクロスポストは嫌われています。MODは代わりに質問を移行できます。

10
@JMD-クロス投稿はまだすべきことではありません。必要に応じて、このような質問の移行プロセスがあります
オデッド

2
@JMDクロスポストしないでください。複数のサイトに適した質問は非常にまれです。今回は、たとえば、あなたの質問はStack Overflowのトピックから外れていました。しかし、あなたの質問が両方のサイトに適していたとしても、サイトの周りであなたの質問を買い物することは一般的に嫌われています。私たちは皆、ここで時間をボランティアで提供しています。少なくとも、クロスポストする前にStack Overflowで得ていた答えを評価するのを待つことができました。
ヤニス

回答:


59

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進数で記述するよりも混乱が少なくなります。これは、1桁の16進数が4ビット(半バイト; 1ニブル)と2から1バイト0x3fに完全に対応するためです。低ニブルに設定し、高ニブルに2ビットを設定します。

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

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

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


もう1つの例は、「マジックナンバー」0xDEADBEEFの使用です。この投稿を参照してくださいstackoverflow.com/questions/5907614/0xdeadbeef-vs-null
Etsitpab Nioliv

45

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

読みやすいです

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;

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

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

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


2
8進数は珍しくありません。0は8進数です:)(Stack Exchangeネットワークのどこかで、今は見つからない)。
gerrit

2
@Earlz:多くの指を持つ人々。:-)
ブライアンオークリー

3
26 x 2 + 10 =すべて大文字、小文字、すべて数字。それほど珍しいことではありません。また、Base 36が使用されていることも確認しました。これは、大文字と小文字を区別しない同じバージョンです。
ダレルホフマン

3
@vasile:1時間に60分、1分に60秒あります。これは、人々がベース60システムを使用していたためです。自然界には、1時間に60分あるはずだと言う何かがあると信じていないことを願っています!
ジョレン

1
はい、彼らは星でそれを読んで、彼らは時間の測定のためにベース-60を使用しました。年間360日(= 6x60)で、60を基準に時間を測定するのはそれほど難しくありません。
-ytg

8

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

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

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

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

さらに学びたい場合は、Charles Petzoldのコードを読むことをお勧めします。


3
コンパイラーは気にしません。リストしたベース間で変換することは確かに簡単ですが、ベース10の単純な(低速の)変換も特に難しくはありません。コンパイラーの構築に役立つほとんどの言語(アセンブリーは使用しません)変換は標準ライブラリで利用できるため、コンパイラーにとっては事実上無料です。

1
Cで16進数を使用しても、より高速なプログラムに変換されません。コンパイラは、使用するベースを気にしません。
チャールズサルビア

5
プログラムのベースに関係なく、コンパイラはコンパイル時にそれをバイナリに変換します。組み立て手順は同じです。
カールビーレフェルト

2
真、偽と「ファイルが見つかりません」:エンタープライズコンピュータは、実際にトライeneryブール値に基づいています
マーティン・ベケット


4

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

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

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

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


8進数は、多くの場合、文字値を指定するために使用され、バイナリデータをダンプする場合もあります。
カレブ

3

他のベースを使用する最も一般的な正当な理由は、ベース2への変換の容易さに関係しています。数字:

 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進数で印刷する必要がありました。

2

コンピューター(正確にはコンパイラー)は、ソースコードで使用する数値ベースをまったく気にしません。最も一般的に使用されるプログラミング言語は、ベース8(8進数)、10(10進数)、および16(16進数)を直接サポートします。いくつかは、ベース2(バイナリ)番号の直接サポートも提供します。特殊言語は、他の数値ベースもサポートする場合があります。(「直接サポート」とは、ソースコード自体のビットシフト、乗算、除算などの数学的なトリックに頼らずに、そのベースに数字を入力できることを意味します。たとえば、Cはベース16を直接サポートします。0x番号プレフィックスと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し、名前がtypeの変数を宣言していることを認識し、n初期値を割り当てます。しかし、その価値は何ですか?

コンピューターにとって、バイトの順序とアライメントの問題を無視すると、変数の初期値の入力は0x31 0x30です。これは、初期値が0x3130(10を基数とした12592)であることを意味しますか?もちろん違います。言語パーサーは、使用されている文字エンコーディングでファイルを読み続ける必要があるため、読み取りの1 0後にステートメントターミネータが続きます。この言語ではベース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型変数の値を保持するのに十分なストレージを割り当て、そこにソースコードから読み取った値を何らかの一時保持変数に配置します。その後、(おそらくかなり後で)結果のバイナリ値をオブジェクトコードファイルに書き込みます。

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

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


1

10以外のベースで番号をプログラムするために誰もが邪魔にならない理由。

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

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

x01-著作権記号(\ u00a9)など、特定のキーボードでは使用できない文字をアプリケーションに表示させたい場合があります。

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

x03-コードを複雑で複雑に見せるために-良いことは、C#が8進定数をサポートしていないことです!


1

重要な問題は、合理的な方法でコンピューターのサイズを1語で表すことです。6502は8ビットプロセッサでした。4004は4ビットプロセッサでした。

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

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

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

所有者、グループ、およびワールドがそれぞれ許可を表す3ビットを持っているUNIXファイル許可(755、644)で、今日でも8進数が表示されます。


数学の世界では、異なる基数で奇妙なことをすることがあります。たとえば、プロジェクトオイラー396の弱いGoodsteinシーケンス、または回文数を使用したより単純なシーケンスです。ベースの数値のプロパティがあるNの倍数である数という1 - Nは、その数字がの倍数にまとめる必要があります1 - Nが。さらに、N-1が完全な正方形の場合、このプロパティはsqrt(N-1)にも存在します。これは、特定の数学的問題にいくつかの用途があります。


1
PDPは、9/18ビットのバイトを持っていたので、進だったあなたがバイトならば、進数はそれほど3ビットを表し、それは多くの意味を作る3で割り切れる
マーティンベケット

1
Octalは16ビットシステム(特にPDP-11)でも使用されました。これは、15(符号ビットを除くビット数)が3にうまく分割されるためです。これは、元のUNIXオペレーティングシステム全体で広く使用されました(たとえば、 「od」はバイナリファイルをダンプするための標準ツールであり、そのデフォルト形式は、許可だけではなく、8ビットの16進数ではなく16ビットの8進数です。また、PDP-11命令セットに2つの6ビットオペランドフィールドがあることも関係する場合があります。
-Random832

Octalは、当時の技術で表示できるため、使用されました。Nexiチューブ、誰か?または他の0-9ディスプレイ?AFディスプレイが表示されるまでに時間がかかりました。
ジェレミーJスターチャー

1

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

ただし、完璧ではありません。ある不幸な会社がIDを持っていた時代がありましたB000BZ


1

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

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


1

基数16(16進数)の数値が非常に頻繁に使用される1つの領域は、特にWebにHTML / CSSを使用する場合の色の指定です。デジタルディスプレイで使用する色は、3つの「基本」色(RGB-赤、緑、青)の3つの輝度値の組み合わせを使用して指定され、1600万色の表示可能色(24ビットカラーを使用) )。

例えば、ヘクスにおける最大強度の緑になり0x00ff00及び65280小数です。今度は、赤と青の等しい部分を持つ半分の色を「手動で」混ぜて、半分の強度で素敵な紫色を作成しようとすることを想像してください:) 16進数では、これは0x80008010進数の値がそうであるように単純に記述されます8388736。グレーの色合いで作業するとき、それはさらに簡単になります- 50%のグレーがある0x808080(16進)、8421504(10進数)、75%がある0xC0C0C012632256、そしてそうで。

16進数の使用ははるかに直感的であり、この色の使用に精通している人は、16進数の値を見るだけですぐに色を「推測」できます。また、同じ色を複数回使用する必要がある場合に使用する傾向があります(通常はそうです)。

クレイジーな量の16進数の使用法については、Webページ(特にCSS)をチェックしてください:D

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


0

一部のアルゴリズムでは、ベース2は他の何よりも理にかなっています。たとえば、二分木または10進木を横断する関数を作成しますか?

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

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

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


2
もちろん、10進ツリーを使用します。2あなたが使用しているこの奇妙なキャラクターは何ですか?
-CodesInChaos

0

何らかの理由で多指症になり、指が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配列内の各ライトは、単一のワード/レジスタで8または16または32または64または128(データ型の幅)に適合する1ビットです。スペース効率が必要であり、むしろ歓迎されています。

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

STRANGE BASEの使用

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



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)
    
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.