32ビットマシンが2 ^ 32までの数しか処理できない場合、マシンをクラッシュさせずに1000000000000(兆)を書き込むことができるのはなぜですか?


370

32ビットコンピュータにのみ店舗2までの整数を締結したことができます31 1 -
私たちは、IPv4アドレスの不足していると64ビットの時代に入ってきた理由です。

しかし、数2 31 - -1(2,147,483,647)が、私は私のマシンがクラッシュすることなく、細かい表示できるように思われる番号1000000000000(1,000,000,000,000)ほどの大きさではありません。

誰かがこれがなぜなのか説明できますか?


35
質問には欠陥があります。32ビットマシンは、2 ^ 32よりもはるかに大きい数を処理できます。彼らはそれを「長い」などでいつもやっています。1つのレジスタに保存できるのは2 ^ 32までですが、ソフトウェアはこの問題を回避するように書かれています。いくつかの現代言語では、与えられた数の長さの問題さえありません。
JFA

23
トピックに関するコメントを丁寧に、質問の技術的な側面に関連させてください。ほぼ50のジョークコメントを既に削除する必要があったため、投稿をロックする必要はありません。ありがとうございました。
ヒンクル

6
この質問は少しずさんな方法で書かれています。数字1000000000000を「書き込み」および「表示」とはどういう意味ですか?質問を書いたときに、1000000000000という数字を書いて、Webブラウザーで問題なく表示されると思いますが、これはコンピューターを使用したことがある人にとっては奇妙なことではないはずです。質問は自由な解釈を求めます。
HelloGoodbye 14年

7
人間の意識は約50ビットを保持すると推定されています(私はどこかで読んだ)。したがって、質問は「10^9PCがクラッシュすることなくどのように書くことができるのか」ではありません。むしろ、「どうすれば10^(18)脳がクラッシュすることなく書くことができますか?」
ハーゲンフォンアイゼン14年

1
32ビットコンピュータは、最大2 ^ 32-1までのUNSIGNED整数のみを格納できます。2^ 32-1は2,147,483,647と等しくさえありません...
コライトゥゲイ

回答:


784

別の質問をして、あなたの質問に答えます。

6本の指でどのように数えますか?

おそらく片方の手で可能な最大数までカウントし、指を使い果たしたらもう片方の手に移動します。コンピューターも同じことを行います。1つのレジスターが保持できる値よりも大きい値を表す必要がある場合、複数の32ビットブロックを使用してデータを処理します。


16
おかしい、@ codename。それでは、指を32以上(つまり、2 ^ 5が使い果たされたら)にどのように数えますか?;)片方の手に移動することの類推は良いです...たとえバイナリがもう片方の手に移動する必要性を遅らせたとしても。 私が見たいのは、1,048,575までのバイナリでさらにカウントするために、つま先に移動するために小児用の器用さで1,024以上にカウントすることです!:)それは潜在的に20ビットのドーターボードの電力です。:P
J0e3gan 14年

14
この回答の技術的な側面の議論に関連するトピックに関するコメントを保管してください。この回答から既に60件以上のジョークコメントが削除されています。投稿をロックする必要はありません。
ヒンクル

@ codename-簡単に、1本の指をスタックポインターとして割り当てます。指を使い果たしたら、スタックに金額を追加し、カウントを再開します。
マカッハ14年

@codenameをどこで知りましたか?私は、フレデリック・ポールからこの最初のは、例えばここを参照してください聞いhjkeen.net/halqn/f_pohl3.htm
ゼイン・

2
これは関連する質問に対する答えではないと思います。@ Bigbio2002による回答は正しいものです。ここで、「1000000000000」は「adsfjhekgnoregrebgoregnkevnregj」のように数字ではなくテキストです。あなたが言っていることは本当ですが、私はこれが正しい答えではないと強く感じています。そして...非常に多くのupvotesを見るために
マスターチーフ

398

32ビット整数は2 ^ 32-1より大きい値を保持できないことは正しいです。ただし、この32ビット整数の値と、それが画面にどのように表示されるかは、2つのまったく異なるものです。印刷された文字列「1000000000000」は、メモリ内の32ビット整数では表されません。

文字通り「1000000000000」を表示するには、13バイトのメモリが必要です。個々のバイトはそれぞれ最大255の値を保持できます。いずれも数値全体を保持できませんが、ASCII文字として個別に解釈されます(たとえば、文字 ' 0'は10進値48、バイナリ値で表されます00110000)。人間であるあなたにとって意味のある形式にまとめられます。


プログラミングの関連概念は型キャストです。これは、コンピューターが0sと1sの特定のストリームを解釈する方法です。上記の例のように、数値、文字、または完全に別のものとして解釈することもできます。32ビット整数は1000000000000の値を保持できない場合がありますが、32ビット浮動小数点数はまったく異なる解釈を使用して保持できます。

コンピューターが内部で大きな数を処理し処理する方法については、64ビット整数(最大160億億の値に対応可能)、浮動小数点値、および任意の大きな数で動作できる特殊なライブラリーが存在します数字。


22
実際、それはほとんど正しいですが、完全ではありません。32ポイントの浮動小数点数は、1000000000000を正確に表すことができるとは考えられません。これは、目的の数に非常に近い数を表しますが、正確には表しません。
ティムB 14年

6
@TimB:decimal32形式について聞いたことがありますか?IEEE 754-2008標準の一部です。この形式は、この番号を正しく表すことができます。)
VX 14年

15
確かに、できます。しかし、それは人々が「浮動」と言うときの形式ではなく、通常、現在のコンピューターの標準の浮動小数点プロセッサーによって保存および使用される32ビット浮動小数点数を指します。
ティムB 14年

2
@TimB確かに。float32として表現できる番号に最も近い番号は999999995904
greggo 14年

4
@TimB:しかし、64ビットの浮動小数点数は簡単に1000000000000正確に表現できます。10 ^ 12、または2 ^ 12 * 5 ^ 12です。5 ^ 12には28ビットの仮数が必要です。
キーストンプソン14年

191

何よりもまず、32ビットコンピューターは1 つのマシンワードに最大2³²-1の数値を格納できます。マシンワードは、CPUが自然な方法で処理できるデータの量です(つまり、そのサイズのデータ​​に対する操作はハードウェアに実装され、一般に実行が最も高速です)。32ビットCPUは32ビットで構成されるワードを使用するため、1ワードに0〜2³²-1の数値を格納できます。

第二に、1兆1000000000000は異なるものです。

  • 1兆は数の抽象的な概念です
  • 1000000000000はテキストです

11回押してから012回押すと、テキストを入力します。1入力10入力0。見る?文字を入力しています。文字は数字ではありません。タイプライターにはCPUやメモリがまったくなく、テキストだけであるため、そのような「数値」をかなりうまく処理していました。

1000000000000が数値ではなくテキストであることの証明 1兆(10進数)、4096(バイナリ)または281474976710656(16進数)を意味する場合があります。さまざまなシステムでさらに多くの意味を持ちます。1000000000000の意味は数値であり、それを格納することは別の話です(すぐに戻ります)。

テキストを(プログラミングではstringと呼ばれる)1000000000000に格納するには、14バイト(各文字に1つと、基本的に「文字列がここで終わる」ことを意味する終端NULLバイト)が必要です。それは4つの機械語です。3つ半で十分ですが、私が言ったように、機械語の操作は最速です。のは、仮定しようASCIIをテキストに保存するために使用され、そのメモリに、それは次のようになります。(に対応するASCIIコードに変換0し、1バイナリにし、別の行の各単語)

00110001 00110000 00110000 00110000
00110000 00110000 00110000 00110000
00110000 00110000 00110000 00110000
00110000 00000000 00000000 00000000

4つの文字が1つの単語に収まり、残りは次の単語に移動します。すべて(最初のNULLバイトを含む)が収まるまで、残りは次の単語に移動します。

さて、数値の保存に戻ります。オーバーフローしたテキストと同じように機能しますが、右から左に適合します。複雑に聞こえるかもしれませんが、ここに例を示します。簡単にするために、次のことを想定してみましょう。

  • 架空のコンピューターは、バイナリーではなく10進数を使用します
  • 1バイトは数字を保持できます 0..9
  • 1ワードは2バイトで構成されます

空の2ワードメモリは次のとおりです。

0 0
0 0

数字4を保存しましょう。

0 4
0 0

それでは、9を追加しましょう。

1 3
0 0

両方のオペランドが1バイトに収まりますが、結果には収まらないことに注意してください。しかし、もう1つ使用する準備ができています。99を保存しましょう:

9 9
0 0

繰り返しますが、2番目のバイトを使用して数値を格納しました。1を追加しましょう。

0 0
0 0

おっと...これは整数オーバーフローと呼ばれ、多くの深刻な問題、時には非常に高価な問題の原因です。

しかし、オーバーフローが発生することが予想される場合、これを行うことができます。

0 0
9 9

そして、1を追加します。

0 1
0 0

バイト区切りのスペースと改行を削除すると、より明確になります。

0099    | +1
0100

オーバーフローが発生し、追加のメモリが必要になる可能性があると予測しました。この方法での数字の処理は、1語に収まる数字ほど高速ではなく、ソフトウェアで実装する必要があります。32ビットCPUに2つの32ビットワード番号のサポートを追加すると、事実上64ビットCPUになります(64ビット番号でネイティブに動作できるようになりましたよね?)。

上記で説明したことはすべて、8ビットバイトと4バイトワードのバイナリメモリにも適用されますが、ほぼ同じように機能します。

00000000 00000000 00000000 00000000 11111111 11111111 11111111 11111111    | +1
00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000000

ただし、このような数値を10進法に変換するのは難しいです。(ただし、16進数はかなりうまく機能します


21
あなたの答えはややひどく読みます。OPは、テキストではなく番号について明確に話している:large as the number 1 trillion (1000000000000)。また、あなたはほとんど話している任意精度演算が、あなたは本当にあなたが....何を言っているかのための条件のいずれかに言及したことがない
MirroredFate

12
「1兆」も文字列です
エルゾヴァルギ14年

3
@ElzoValugiです。数値を表す文字列とは対照的に、抽象的な数値の概念を提示する方法を見つける必要がありました。私は「1兆」がそれを行うためのより良くて曖昧でない方法だと信じています(答えの証明を参照)。
グロノスタジ14年

25
@MirroredFate私は「数字についてはっきりと話している」ことに同意しません。OPは明らかにされ、「細かい表示」と言っている ...私には、テキスト「1000000000000」の話
ジョー・

4
@yannbane 'A'は文字であり、数字ではありません。「?」数字ではなく文字です。「1」は文字であり、数字でもありません。文字は単なる記号です。数字または数字を表すことができますが、間違いなく数字ではありません。「1」は1、10、100、1000などを表すことができます。これは、数字またはその一部になり得る数字を表す単なる記号です。「10」(文字列)は2、8、10、または16などを意味しますが、リンゴが10個あると言うときは、10を使用しているので、誰もがその意味を知っています。文字と数字には大きな違いがあります。
グロノスタジ14年

40

また、コンピューターがクラッシュすることなく「この声明は間違っています」と書くこともできます。解釈されます。

編集:今であまり皮肉さまざまな方法でより有用な情報の数は、メモリに保存することができます。これらをより高い抽象化で説明します。つまり、現代のプログラマが実行のためにマシンコードに変換される前にコードを記述している可能性があるという点です。

コンピューター上のデータは特定のタイプに制限する必要があり、そのようなタイプのコンピューター定義は、このデータに対して実行できる操作とその方法(数値の比較、テキストの連結、ブール値のXOR)を記述します。数値にテキストを掛けることができないように、単純に数値にテキストを追加することはできません。そのため、これらの値の一部はタイプ間で変換できます。

符号なし整数から始めましょう。これらの値タイプでは、すべてのビットが数字に関する情報を保存するために使用されます。yoursは32ビットの符号なし整数の例で、そこに0toの値を2^32-1保存できます。はい、使用するプラットフォームの言語またはアーキテクチャに応じて、16ビット整数または256ビット整数を使用できます。

否定的になりたい場合はどうしますか?直観的に、符号付き整数はゲームの名前です。条約はからすべての値を割り当てることである-2^(n-1)2^(n-1)-1私たちは書くための二つの方法で対処することの混乱を避けるこの方法- +0とします-0。したがって、32ビットの符号付き整数は、から-2147483648までの値を保持します2147483647。きちんとしましたね。

わかりました、10進成分のない数値である整数をカバーしました。これらを表現するのは難しいです:非整数部分は0との間のどこかにしか分からない1ので、それを記述するために使用される余分なビットはすべて、精度を高めます:1 / 2、1 / 4、1 / 8 ...問題は、あなたです0.1分母に2のべき乗しか持てない分数の合計として単純な10進数を正確に表現できない!数値を整数として保存する方がはるかに簡単ではありませんが、代わりに基数(10進)ポイントを置くことに同意しますか?これは固定小数点数と呼ば、保存1234100しますが、1234.100代わりにそれを読み取る規則に同意します。

計算に使用される比較的一般的なタイプはfloating pointです。動作方法は本当にすてきです。1ビットを使用して符号値を格納し、次に一部を使用して指数と仮数を格納します。このような割り当てを定義する標準はありますが、32ビットの浮動小数点数の場合、保存できる最大数は圧倒的です

(2 - 2^-23) * 2^(2^7 - 1) ≈ 3.4 * 10^38

ただし、これには精度が犠牲になります。ブラウザで利用可能なJavaScriptは64ビットの浮動小数点数を使用しますが、それでも物事を正しく行えません。これをアドレスバーにコピーしてEnterキーを押します。スポイラー警告:結果がされていないことになるだろう0.3

javascript:alert(0.1+0.2);

Microsoft .NET 4.5のようなより多くの代替タイプがありますがBigInteger、理論的には上限も下限もなく、「バッチ」で計算する必要があります。しかし、より魅力的な技術は、Wolfram Mathematicaエンジンなどの数学を理解する技術であり、無限大などの抽象的な値を正確に処理できます


8
あなたはこの現実でそれをすることができます。スタートレックの世界でそれをやってみてください。すべての火花と煙のために、前に立ちます。
マイケルペトロッタ14年

これは、固定小数点が正確に機能する方法ではありません。実際には、小数点を生成するために数値がスケーリングおよびバイアスされるシステムです。あなたの例では、スケールは1/1000ですが、次のような固定小数点数(特にコンピューターグラフィックス)もあります:0 = 0.0、255 = 1.0-スケールは1/255です。
アンドンM.コールマン14年

31

重要なのは、コンピューターが数字をエンコードする方法を理解することです。

確かに、コンピューターが単一の単語(32ビットシステムでは4バイト)を使用した単純なバイナリ表現を使用して数値を格納することを要求する場合、32ビットコンピューターは最大2 ^ 32までの数値しか格納できません。ただし、数字をエンコードする方法は他にもたくさんあります。

1つの例は、コンピューターが浮動小数点数を格納する方法です。コンピューターは、さまざまな方法を使用してエンコードできます。標準IEEE 754は、2 ^ 32より大きい数値をエンコードするための規則を定義しています。粗いことに、コンピューターは、32ビットを数の桁を表す異なる部分と数のサイズを表す他のビット(つまり、指数10 ^ x)に分割することでこれを実装できます。これにより、はるかに広い範囲が可能になりますサイズの観点から数字を使用しますが、精度は低下します(多くの目的で問題ありません)。もちろん、コンピューターはこのエンコードに複数の単語を使用して、使用可能なエンコードされた数値の大きさの精度を高めることもできます。IEEE規格の単純な10進数32バージョンでは、10進数で約7桁の精度の数値と、最大約10 ^ 96の数値を使用できます。

しかし、追加の精度が必要な場合、他の多くのオプションがあります。明らかに、エンコードでより多くの単語を無制限に使用できます(ただし、エンコードされた形式に変換したり、エンコードされた形式から変換するとパフォーマンスが低下します)。これを行う1つの方法を調べたい場合は、計算で数百桁の精度を可能にするエンコードスキームを使用するExcel用の優れたオープンソースアドインがあります。アドインはXnumbersと呼ばれ、ここから入手できます。コードはVisual Basicであり、可能な限り高速ではありませんが、理解および変更が容易であるという利点があります。これは、コンピューターがより長い数字のエンコードを達成する方法を学ぶのに最適な方法です。また、プログラミングツールをインストールしなくても、Excel内で結果を試すことができます。


24

それはすべてあなたの質問です。

好きな数字を紙に書くことができます。白い紙に1兆個のドットを書いてみてください。遅くて効果がありません。そのため、これらの大きな数字を表す10桁のシステムがあります。「ミリオン」、「兆」などの大きな数字の名前もありますので、one one one one one one one one one one one...大声で言わないでください。

32ビットプロセッサは、32桁の正確な長さのメモリブロックで最も迅速かつ効率的に動作するように設計されています。しかし、私たち人々は一般に10桁の数値システムを使用し、コンピューターは電子的であるため、2桁のシステム(バイナリ)を使用します。32と64の数字はたまたま2の累乗です。100万と1兆は10の累乗です。たとえば、65536の多数の数字よりも、これらの数字を操作する方が簡単です。

紙に書くとき、大きな数字を数字に分解します。コンピューターは、数字をより大きな数字に分解します。私たちは好きな数を書き留めることができますし、そのように設計すればコンピュータも書き留めることができます。


15

32ビットと64ビットはメモリアドレスを参照します。コンピュータのメモリは私書箱のようなもので、それぞれが異なるアドレスを持っています。CPU(中央処理装置)はこれらのアドレスを使用して、RAM(ランダムアクセスメモリ)上のメモリ位置をアドレス指定します。CPUが16ビットのアドレスしか処理できない場合、32 MBのRAMしか使用できませんでした(当時は非常に大きかったようです)。32ビットでは、4 + gbになりました(当時、これは巨大なようでした)。64ビットのアドレスができたので、RAMはテラバイトになります(これは巨大なようです)。
ただし、プログラムは、数値やテキストの保存などに複数のメモリブロックを割り当てることができます。これは、プログラム次第であり、各アドレスのサイズには関係ありません。したがって、プログラムはCPUに伝えることができ、ストレージの10アドレスブロックを使用してから、非常に大きな数、または10文字の文字列などを格納します。
追記:メモリアドレスは「ポインタ」によってポイントされるため、32ビットと64ビットの値は、メモリにアクセスするために使用されるポインタのサイズを意味します。


2
詳細を除いて良い答えです-16ビットのアドレス空間は、32MBではなく64KBを提供し、286のようなマシンには24ビットのアドレスがありました(16MB用)。また、64ビットアドレスでは、テラバイトをはるかに超えます-16エクサバイトのように-テラバイトは、アドレスのサイズではなく、現在の世代のマザーボード/ CPUが課している制限のようなものです。
フィル14年

4
32ビットは、メモリアドレスではなくマシンワードサイズを指します。Philが述べたように、286は16ビットCPUでしたが、メモリセグメンテーションによるアドレス指定に24ビットを使用しました。x86 CPUは32ビットですが、36ビットのアドレス指定を使用します。PAEを参照してください。
グロノスタジ14年

@gronostaj well x86には、386からPentiumへの32ビットアドレス指定があります。
ルスラン14年

ここで唯一の正しい答えであるため、賛成票を投じてください-32ビットは32ビット算術ではなく、32ビットメモリアドレッシングを指します。
user1207217 14年

@ user1207217:?? あなたの推論によれば、たとえばZ80または8080は16ビットプロセッサです(16ビットのメモリアドレッシングとメモリバスのため)?
パブーク14年

13

数字の表示は整数ではなく個々の文字を使用して行われるためです。数値の各数字は、使用されるエンコーディングによって定義される整数値の個別の文字リテラルで表されます。たとえば'a'、ascii value 97で表されますが、'1'はで表され49ます。こちらasciiテーブルを確認してください。
「a」と「1」の両方を表示する場合は同じです。これらは文字リテラルであり、整数ではありません。各文字リテラルは、8ビットまたは1バイトサイズで値を格納する32ビットプラットフォームで最大255の値を持つことができます(ただし、プラットフォームに依存しますが、8ビットが最も一般的な文字サイズです)。表示されます。表示できる個別の文字の量は、使用しているRAMによって異なります。RAMが1バイトしかない場合は1文字しか表示できません。RAMが1GBある場合は、1024 * 1024 * 1024文字を表示できます(計算が面倒です)。

ただし、この制限は計算に適用されますが、IPV4標準に興味があると思います。コンピューターの完全に関連しているわけではありませんがbit-size、何らかの形で規格に影響を与えています。IPV4標準が作成されると、IP値が32ビット整数で保存されました。一度サイズを指定すると、標準になりました。インターネットについて知っていることはすべてそれに依存していたため、割り当てるIPアドレスが不足していました。したがって、IP標準が64ビットに修正された場合、ルーター(これは正しいと思います)やその他のネットワークデバイスなど、すべてが機能しなくなります。そのため、32ビット整数を128ビット1と交換した新しい標準を作成する必要があります。そして、残りの標準を調整しました。ハードウェアメーカーは、この新しい標準をサポートすることを宣言するだけで、バイラルになります。それほど単純ではありませんが、ここでポイントを得たと思います。

免責事項:ここで述べたポイントのほとんどは私の仮定に忠実です。ここでは、簡単にするために重要な点を見落としているかもしれません。私は数字が得意ではないので、いくつかの数字を逃したに違いありませんが、ここでのポイントは、PCがクラッシュしない理由についてOPの回答に返信することです。


2
断言していませんが、あなたの答えには多くの問題があります。1ASCIIでは0x31であり、0x1ではありません。1 GB = 1024 ^ 3 B. 32ビットCPUが導入される前にIPv4が発明されたため、アドレスが32ビット整数で保存されていると言うことはOPの質問と矛盾しています。最後に、IPv6は64ビットではなく128ビットのアドレスを使用しています。
グロノスタジ14年

13

プロセッサには、「単語」があります。別の言葉があります。人々が「32ビットプロセッサ」と言うとき、それらはほとんど「メモリバス幅」を意味します。この単語は異なる「フィールド」で構成され、送信(24ビット)および制御(その他のビット)に対応するコンピューターのサブシステムを指します。正確な数字については間違っている可能性があります。マニュアルで確認してください。

完全に異なる側面は計算です。SSEおよびMMX命令セットは、長整数を格納できます。生産性を損なうことのない最大の長さは、現在のSSEバージョンに依存しますが、常に約64ビットの倍数です。

現在のOpteronプロセッサは256ビット幅の数値を処理できます(整数についてはわかりませんが、floatは確かです)。

要約:(1)バス幅は計算幅に直接接続されていない、(2)異なるワード(メモリワード、レジスタワード、バスワードなど)でも互いに接続されていない場合24.多くのプロセッサは、6ビットワードを使用しました(ただし、その歴史も)。


真実ではありませんが、元のPentiumプロセッサは、32ビットプロセッサであったにもかかわらず、高いメモリ帯域幅のために64ビットデータバスを備えていました。8088は、8ビットデータバスを備えた16ビットプロセッサでした。
doug65536

10

一般に、コンピューティングデバイスの目的は、データを受け入れ、処理し、保存し、送信することです。基礎となるハードウェアは、これらの4つの機能の実行を支援する単なるマシンです。それはソフトウェアなしではできません。

ソフトウェアは、データを受け入れる方法、データを処理する方法、保存する方法、および他の人に提供する方法をマシンに伝えるコードです。

基盤となるハードウェアには常に制限があります。32ビットマシンの場合、データを処理するレジスタのほとんどは32ビット幅です。これは、マシンが2 ^ 32を超える数を処理できないことを意味しませんが、より大きな数を処理したい場合、マシンがそれを受け入れ、処理し、保存するのに1サイクル以上かかることがありますまたはそれを放出します。

ソフトウェアは、マシンに数字の処理方法を指示します。ソフトウェアが大量を処理するように設計されている場合、大量の処理方法を指示する一連の命令をCPUに送信します。たとえば、2つの32ビットレジスタで番号を表すことができます。番号に1,234を追加する場合、ソフトウェアはCPUに最初に下位レジスタに1,234を追加するように指示し、オーバーフロービットをチェックして、その加算が下位レジスタには大きすぎる数値になるかどうかを確認します。もしそうなら、それは1を高音域に追加します。

小学生がキャリーで加算するように教えられるのと同じ方法で、CPUは単一のレジスターで保持できる数よりも大きい数を処理するように指示できます。これは、実用的なサイズの数値のほとんどの一般的な数学演算に当てはまります。


10

違いは、データをコンピューターに保存する方法にあります。

理論上の8ビットマシンの場合、単一のプロセッサレジスタまたはメモリアドレスに格納できるのは2 ^ 8の値のみです。(これは、使用するプロセッサ、メモリアーキテクチャなどに基づいて、「マシン」から「マシン」まで変化することに注意してください。しかし、今のところ、仮想の「ステレオタイプ」マシンに固執しましょう。)

理論的な16ビットマシンでは、レジスタ/メモリの場所の最大値は2 ^ 16、32ビットマシンでは2 ^ 32などになります。

長年にわたり、プログラマーは、単一のプロセッサレジスタまたはメモリアドレスに格納できる数よりも大きい数を格納および処理するために、あらゆる種類の詐欺師を考案してきました。多くの方法が存在しますが、それらはすべて、複数のレジスタ/メモリアドレスを使用して、「ネイティブ」レジスタ/メモリロケーション幅よりも大きい値を格納する必要があります。

これらの方法はすべて、マシンがネイティブの容量よりも大きい値を保存/処理できるという点で有益です。欠点は、ほとんどすべてのアプローチが複数のマシン命令/読み取り/などを必要とすることです。これらの番号を処理します。場合によっては、これは問題ではありません。多数(特に大きなメモリアドレス)を大量に処理する場合、関連するオーバーヘッドにより速度が低下します。

したがって、レジスタ、メモリの場所、およびメモリアドレスハードウェアを「より広く」より広くして、多数を「ネイティブに」処理し、そのような数を最小限の操作で処理できるようにするという一般的な要望。

数値のサイズは無限であるため、プロセッサのレジスタ/メモリのサイズ/アドレス指定は常に、ネイティブの数値のサイズと、ますます大きな幅を実装するためのコストのバランスです。


8

32ビットコンピューターは、1つのマシンワードに最大2 ^ 32までの数値しか格納できませんが、それは、データのより大きなエンティティを処理できないという意味ではありません。

32ビットコンピューターの意味は、一般にデータバスとアドレスバスが32ビット幅であることです。つまり、コンピューターは4 GBのメモリアドレススペースを一度に処理し、データバスを介して一度に4バイトのデータを送信できます。 。

ただし、コンピューターがより多くのデータを処理することを制限するものではなく、データバスを介して送信する場合、データを4バイトのチャンクに分割するだけです。

通常のIntel 32ビットプロセッサは、128ビットの数値を内部で処理できるため、100000000000000000000000000000000000000などの数値を問題なく処理できます。

コンピュータで処理するよりもはるかに大きな数を処理できますが、計算はソフトウェアで実行する必要があり、CPUには128ビットを超える数を処理するための命令がありません。(浮動小数点数の形式ではるかに大きな数を処理できますが、精度は15桁しかありません。)


6

他の多くの回答にメモを追加するだけです。これは、この質問の非常に重要な事実であり、見逃されているためです。

「32ビット」は、メモリアドレス幅を指します。レジスタサイズとは関係ありません。多くの32ビットCPUには、64ビットまたは128ビットのレジスタがあります。特にx86製品ラインについて言えば、最近のコンシューマCPUはすべて64ビットで、特別な目的のために最大256ビットのレジスタを備えています。

レジスタ幅とアドレス幅のこの違いは、4ビットのレジスタと8ビットのアドレス、またはその逆の古代から存在していました。

他の回答で説明されているように、レジスタサイズに関係なく、大きな数を格納しても問題はないことがわかります。

レジスタは、どんなサイズの彼らは、さらにもできることが起こるかもしれ理由算出し、より大きな数字では大きすぎて計算がそれだけで小さなもう少し複雑です(レジスタに収まらない、いくつかの小さなものに分けることができるということです実際に)。


それは本当ではありません。64ビットが参照するものは一貫性がありませんが、64ビットのレジスタ幅を持つシステムは64ビットと呼ばれます。ウィキペディアによると、「64ビットのコンピューターアーキテクチャには、一般に64ビット幅の整数レジスタとアドレス指定レジスタがあります」。はい、最新のx86(またはAMD-64)製品ラインには巨大な専用レジスタがありますが、64ビットのメインレジスタがあり、48〜52ビットのメモリにアクセスできます。古いx86システムには32ビットのメインレジスタがあり、24〜36ビットのメモリにアクセスします。8086は16ビットチップと呼ばれ、16ビット幅のレジスタがあり、20ビットのメモリにアクセスしました。
prosfilaes

@prosfilaesそれは多くの貴重な情報であり、それらについて言及していました(詳細を覚えていなかったのと、あなたがカントーをしたのを覚えていませんでした)。これを答えに自由に編集してください。
マフ14年

6

すでに与えられた答えは実際にはかなり良いものですが、それらは異なる側面から問題に対処する傾向があり、したがって不完全な絵を提示する傾向があります。私の意見では、それらは技術的にも少し過剰です。

それで、他の答えのいずれかで示唆されているが明示的に表されていない何かを明確にするために、私はそれが問題の核心だと思う:

あなたはあなたの質問いくつかの概念を混同しており、そのうちの1つ(「32ビット」)は実際にはさまざまな異なるものを参照できます(そして異なる答えは異なる解釈を想定しています)。これらの概念は全てのビット数(1と0)を使用(または使用可能)様々なコンピューティングコンテキスト(私はこれで意味うまくいけば、以下の例で明らかにされる)、その概念ではあるとは何かを持っているそれ以外の場合は無関係

明示的に:

  • 「IPv4 / 6」は、インターネットプロトコルインターネット上で情報をパッケージ化および解釈する方法を定義する一連のルールを指します。IPv4とIPv6の主な(または少なくとも最もよく知られている)違いは、アドレス空間(つまり、ネットワーク上の異なる場所を区別するために使用できるアドレスのセット)がIPv6で大きいことです。これは、ネットワークを介して送信されるデータの各パケットのビットが、パケットの送信者と目的の受信者を識別するために割り当てられている(つまり、目的のために確保されている)ことと関係があります。
    • 非計算アナロジー:各パケットは、カタツムリメールで送信される手紙のようなものであり、アドレススペースは、封筒に住所と返信先住所を書き込むときに「許可」される文字の量のようなものです。
    • 私はこれまでのところ、他の回答のいずれにも言及されていません。
  • コンピュータメモリの「ワード」(32ビットおよび64ビット)は、一般的に、コンピュータが使用する、または「考える」データの最小部分と考えることができます。これらのデータのビットは、他のデータのビットを構成するために集まっています、テキストのチャンクまたはより大きな整数など。
    • 非計算アナロジー:単語は、紙の上の単語を構成する文字のように、または思考の列の個々の単語としてさえ考えることができます。
    • 参照してくださいGuffaの答えsanarisの答え、との最初の段落gronostajの答えを
  • 32ビットポインターは単語である場合とそうでない場合がありますが、それでもアトミックに処理されます(つまり、小さなコンポーネントに分割できない個々のユニットとして)。ポインターは、コンピューターがメモリ内の任意のデータチャンクの場所を記録できる最低レベルの方法です。ポインタが「ポイント」できるメモリ位置はできるだけ多くあるため、コンピュータ(または実際にはオペレーティングシステム)が使用するポインタサイズは、単一のポインタでアクセスできるメモリの範囲を制限することに注意してください。ポインター自体に可能な値があるため。これは、IPv4ができ、インターネットアドレスの範囲を制限する方法に似ていますが、いませんたとえば、特定のWebページに存在できるデータの量を制限します。ただし、ポインターのサイズは、ポインターがポイントできるデータ自体のサイズを制限しませ。(データサイズがポインター範囲を超えることを許可するスキームの例については、Linuxのiノードポインター構造を確認してください。これは、ポインターが通常、ランダムアクセスメモリ、ハードドライブ領域ではありません。)
    • 非コンピューターの類推:うーん....これは少しトリッキーです。ライブラリ素材にインデックスを付けるためのデューイ十進法は、おそらく少し似ていますか?または、任意のインデックスシステムです。
    • SiteNookの回答を参照してください。
    • 上記のポインターの説明では、いくつかの微妙な詳細が隠されており、間違いなく完全に正しいわけではないことに注意してください。ただし、プログラマーがポインターを直接操作するプログラミング言語では、実際に使用するには、ここで説明したメンタルモードで十分です。
  • コンピュータは、「表示すること」であることを数値コンピュータのハードウェアやオペレーティングシステムによって制限される(実際的な目的のために)ではありません。他のテキストと同様に扱われます。

これは、フレーズ「32ビット」の解釈の包括的なリストであることを意図していないことに注意してください。

余分なクレジット:数値とコンピューターメモリの原始的なチャンクとの間の基本的な哲学的区別を実際に確認するには、Turingマシンについて少し読んでください。


IPv4への言及は、IPv4アドレスの数が符号付き32ビット整数の長さに実質的に制限されているのに対し、IPv6は128ビットを使用するため、より多くの桁のアドレスを持つことができると指摘したためだと思います。
クロンネックス

@Clonkexおそらく、それは間違いではありませんが、質問は言い表されています。
カイルストランド

5

たとえば電卓で1000000000000と入力すると、コンピューターは小数点付きの実数型として計算します。あなたが言及した32ビットの制限は、小数点なしのすべての整数型の数字に触れます。データタイプが異なると、ビット/バイトを取得する方法が異なります。

整数型の番号:この表は、ポイント(http://msdn.microsoft.com/en-us/library/296az74e.aspx)を把握するのに役立ちます。これは、C ++の制限に影響します。たとえば、Int64型番号には-9223372036854775808から9223372036854775807までの制限があります。

実数型:実数型には浮動小数点指数を含む値が含まれ、より大きな数値を入力できますが、精度/精度は制限されます。(http://msdn.microsoft.com/en-us/library/6bs3y5ya.aspx)たとえば、C ++のLDBL(ラージダブル)には最大指数308があるため、結果番号を入力したり、結果として持ったり9.999 x 10^308することができます。理論的には308(+1)桁です9が、15桁の最も重要な桁のみがそれを表すために使用され、残りは失われ、精度が制限されます。

さらに、さまざまなプログラミング言語があり、数の制限の実装が異なる場合があります。したがって、特殊なアプリケーションがC ++よりもはるかに大きい(および/またはより正確/正確な)数を処理できると想像できます。


この「答え」は間違っています。電卓は、切り捨てエラーを回避するためにBCD番号表現を使用します。IE 0.1 10進数は、有限長の2進数として正確に表現できません。
おがくず

5

典型的なLinuxシステム上の多数のプログラムが多数の処理と出力を処理する実用的な例が必要な場合:

libgmp- GNU多重精度演算ライブラリは、 Linuxシステム上でこの目的のために最も広く使用されているライブラリです。2 ^ 80に1000を掛ける簡単な例:

#include <gmp.h>

// Each large integer uses the mpz_t type provided by libgmp
mpz_t a_large_number;
mpz_t base;
mpz_t result;

// Initalize each variable
mpz_init(a_large_number);
mpz_init(base);
mpz_init(result);

// Assign the number 2 to the variable |base|
mpz_set_ui(base, 2);

// Raise base^80 (2^80), store the result in |a_large_number|
mpz_pow_ui(a_large_number, base, 80);

// Multiply |a_large_number| by 1000, store the result in |result|
mpz_mul_ui(result, a_large_number, 1000);

// Finally, output the result in decimal and hex notation
gmp_printf("decimal: %Zd, hex: %ZX\n", result, result);

したがって、基本的には、通常の+-* /演算子を使用するのと同じです。数字を分割して複数のマシンワードサイズの(つまり32ビット)数字として内部に格納するライブラリを使用するだけです。テキスト入力から整数型への変換を処理するためのscanf()型関数もあります。

の構造は、mpz_tスコットチェンバレンの両手で6まで数える例とまったく同じです。基本的には機械語サイズのmp_limb_tタイプの配列であり、数値が大きすぎて機械語に収まらない場合、GMPは複数mp_limb_tを使用して数値の高/低部分を格納します。


5

頭の中で知っているのは10桁だけです。0〜9。脳内では、これは確かにコンピューターとは異なる方法でエンコードされます。

コンピューターはビットを使用して数値をエンコードしますが、それは重要ではありません。これは、エンジニアがコードをエンコードするために選択した方法ですが、無視する必要があります。32ビットコンピューターには40億を超える異なる値の一意の表現があり、人間には10の異なる値の一意の表現があると考えることができます。

より多くの数を理解する必要があるときはいつでも、システムを使用します。左端の数字が最も重要です。次の10倍の重要性があります。

同様に、40億の異なる値を区別できるコンピューターは、値のセットの左端の値を、そのセットの次の値の40億倍重要にする必要があります。実際、コンピューターはまったく気にしません。数字に「重要性」を割り当てません。プログラマーはそれを処理する特別なコードを作成する必要があります。

値が一意のシンボルの数(人間の頭の中では9)よりも大きくなるたびに、左側の数字に1を追加します。

3+3=6

この場合、数はまだ単一の「スロット」内に収まります

5+5=10. This situation is called an overflow.

そのため、人間は常に十分な一意のシンボルがないという問題に対処します。これを処理するシステムがコンピューターにない限り、余分な数字があったことを忘れて0を書き込むだけです。幸いなことに、コンピューターにはこの場合に発生する「オーバーフローフラグ」があります。

987+321 is more difficult.

あなたは学校で方法を学んだかもしれません。アルゴリズム。アルゴリズムは非常に簡単です。左端の2つのシンボルを追加することから始めます。

7+1=8, we now have ...8 as the result so far

次に、次のスロットに移動して、同じ追加を実行します。

8+2=10, the overflow flag is raised. We now have ...08, plus overflow.

オーバーフローが発生したため、次の数値に1を追加する必要があります。

9+3=12, and then we add one due to overflow. ...308, and we had another overflow.

追加する数字はもうないので、オーバーフローフラグが発生したため、スロットとinser 1を作成します。

1308

コンピューターはまったく同じように動作しますが、人間のような10個だけではなく、2 ^ 32個またはさらに優れた2 ^ 64個の異なるシンボルがあります。

ハードウェアレベルでは、コンピューターはまったく同じ方法を使用してシングルビットで動作します。幸いなことに、それはプログラマーのために抽象化されています。ビットは2桁のみです。これは、電力線で簡単に表現できるためです。ライトが点灯しているか、消灯しています。

最後に、コンピューターは任意の数字を単純な文字列として表示できます。それがコンピューターの長所です。文字のシーケンスと内部表現を変換するアルゴリズムは非常に複雑です。


、私の心、私は36を知っているが、私は一般的にのみそれらの16を使用します。
カイルストランド

「コンピューターはビットを使用して数値をエンコードしますが、それは重要ではありません。」ユーザーが約32ビットの単語を尋ねるコンテキストでは、2 ^ 32-1より大きい数を格納するためにそれらをどのように使用するかが非常に重要です。
HörmannHH

脳の記憶に数字をどのようにエンコードするかは重要ではありません。表現の数には限りがあります。ほとんどが10種類のシンボルを学びました。脳内では、これはおそらく数千のニューロンとシナプスの形で表されます。コンピューターでは、電気の形で表されるか、電力線に電気が流れません。プログラミングの観点から-または数学を学習する場合、CPUの特定のセットに対して直接プログラミングしているまれなケースを除いて、それはまったく重要ではありません。彼は、個々のビットではなく、32ビットと64ビットについて尋ねています。
frodeborli

3

(コンピュータに関する限り)数字ではなく、文字列、または数字のシーケンスを表示しているためです。確かに、数字を扱う一部のアプリ(電卓など)は、そのような数字を処理できると思います。私は彼らがどんなトリックを使っているのか知らない...私は他のいくつかの、より精巧な答えがそれをカバーしていると確信している。


0

この回答の内容のほとんどは、当初から来たこの答えは(他の質問が重複としてマークされていた前に書かれました)。したがって、8ビット値の使用について説明します(この質問は32ビット値について尋ねましたが)。ただし、8ビット値は概念的に理解しやすく、32ビット算術演算などのより大きな値にも同じ概念が適用されるため問題ありません。

8ビットの2つの数値を追加すると、取得可能な最大の数値(0xFF + 0xFF = 1FE)になります。実際、8ビットの2つの数値を乗算しても、取得できる最大の数値(0xFF * 0xFF = 0xFE01)は16ビットであり、8ビットの2倍です。

ここで、xビットプロセッサはxビットのみを追跡できると仮定しているかもしれません。(たとえば、8ビットプロセッサは8ビットしか追跡できません。)それは正確ではありません。8ビットプロセッサは、8ビットチャンクでデータを受信します。(これらの「チャンク」には通常、「ワード」という正式な用語があります。8ビットプロセッサでは、8ビットワードが使用されます。64ビットプロセッサでは、64ビットワードを使用できます。)

したがって、コンピューターに3バイトを与える場合:
バイト#1:MUL命令
バイト#2:上位バイト(例、0xA5)
バイト#3:下位バイト(例、0xCB)
コンピューターは、次の結果を生成できます。 8ビット以上です。CPUは次のような結果を生成する場合があります:
0100 0000 0100 0010 xxxx xxxx xxxx xxxx 1101 0111
aka:
0x4082xxxxD7
さて、それをあなたのために解釈させてください

「40」については、後ほど詳しく説明します。
82は、一連の8ビットである「A」レジスタの一部です。
xxとxxは、「B」レジスタと「C」レジスタという2つの他のレジスタの一部です。これらのビットを0または1で埋めなかった理由は、(CPUに送信される)「ADD」命令が命令によって変更されない可能性があるためです(この例で使用する他のビットのほとんどは一部のフラグビットを除き、変更されます)。
D7は、「D」レジスタと呼ばれるより多くのビットに収まります。
レジスタは単なるメモリです。レジスタはCPUに組み込まれているため、CPUはRAMスティック上のメモリと対話する必要なくレジスタにアクセスできます。

したがって、0xA5 x 0xCBの数学的な結果は0x82D7です。

さて、なぜビットがAおよびBレジスタ、またはCおよびDレジスタの代わりにAおよびDレジスタに分割されたのですか?繰り返しますが、これは私が使用しているサンプルシナリオであり、実際のアセンブリ言語(Intel 8080および8088と多くの新しいCPUで使用されるIntel x86 16ビット)と概念がかなり似ていることを意味します。一般的に、カウント操作のインデックスとして使用される「C」レジスター(ループの場合が一般的)、およびメモリー位置の指定に役立つオフセットの追跡に使用される「B」レジスターなどの一般的なルールがあります。そのため、一部の一般的な算術関数では「A」と「D」がより一般的です。

各CPU命令には、アセンブリでプログラミングする人々が使用するドキュメントが必要です。そのドキュメントでは、各命令で使用されるレジスタを指定する必要があります。(使用するレジスタの選択は、アセンブリ言語プログラマではなく、CPUの設計者によって指定されることがよくあります。ただし、ある程度の柔軟性はあります。)

さて、上記の例の「40」に戻りましょう。これは、「フラグレジスタ」と呼ばれることが多い一連のビットです。フラグレジスタの各ビットには名前があります。たとえば、結果が1バイトの結果を格納できるスペースよりも大きい場合、CPUが設定する「オーバーフロー」ビットがあります。(「オーバーフロー」ビットはしばしば「OF」の省略名で呼ばれることがあります。これは大文字ではなく、ゼロです。)ソフトウェアはこのフラグの値を確認し、「問題」に気付くことができます。このビットでの作業は、高レベルの言語で目に見えないように処理されることが多いため、初心者プログラマーはCPUフラグと対話する方法を学習しないことがよくあります。ただし、アセンブリプログラマは一般に、これらのフラグの一部に他の変数と非常によく似た方法でアクセスする場合があります。

たとえば、複数のADD命令がある場合があります。1つのADD命令は16ビットの結果をAレジスタとDレジスタに格納しますが、別の命令は単にAレジスタに下位8ビットを格納し、Dレジスタを無視し、オーバーフロービットを指定します。その後、(Aレジスタの結果をメインRAMに格納した後)レジスタ(おそらくAレジスタ)に上位8ビットのみを格納する別のADD命令を使用できます。オーバーフローフラグを使用する必要があるかどうか使用する乗算命令に依存します。

(通常、「アンダーフロー」フラグもあります。これは、必要な結果に収まらないほど多く減算した場合に備えています。)

複雑さを示すため
に、Intel 4004は4ビットCPU
でしたIntel 8008は8ビットCPUでした。A、B、C、Dという名前の8ビットレジスタがありました
。Intel8086は16ビットCPUでした。AX、BX、CX、およびDXという名前の16ビットレジスタがありました。
Intel 80386は32ビットCPUでした。EAX、EBX、ECX、およびEDXという名前の32ビットレジスタがありました。
Intel x64 CPUには、RAX、RBX、RCX、およびRDXという名前の64ビットレジスタがあります。x64チップは、16ビットコードを(一部の動作モードで)実行でき、16ビット命令を解釈できます。そうするとき、AXレジスタを構成するビットはEAXレジスタを構成するビットの半分であり、それはRAXレジスタを構成するビットの半分です。したがって、AXの値を変更するときはいつでも、AXが使用するビットはRAXが使用するビットの一部であるため、EAXとRAXも変更します。(EAXを65,536の倍数の値で変更すると、下位16ビットは変更されないため、AXは変更されません。EAXを65,536の倍数でない値で変更すると、AXにも影響します)

私が言及したものよりも多くのフラグとレジスタがあります。単純な概念例を提供するために、一般的に使用されるものをいくつか選択しました。

現在、8ビットCPUを使用している場合、メモリに書き込むときに、4ビットまたは16ビットのアドレスではなく、8ビットのアドレスを参照できるという制限があります。詳細はCPUによって異なりますが、このような制限がある場合、CPUは8ビットワードを処理している可能性があります。そのため、CPUは「8ビットCPU」と呼ばれます。


私の答えの一部が、この質問に対する他の答えのいくつかを繰り返しているように感じます。しかし、別の質問のために書いたので、最初にコンテンツを書いたとき、これは気づきませんでした。また、C言語のコードを含むAnimismの回答には感謝していますが、CPUの実際のアクション/設計により近いAssemblyの動作に関する詳細をコンテンツが提供していると感じました。したがって、私の答えは、他のすべての「より良い」優れた答えを目指しているのではなく、単に補足的なものです。洞察を追加して別の視点を追加
TOOGAM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.