web-dev-qa-db-ja.com

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

32ビットコンピュータは2までの符号付き整数しか格納できません31 - 1。
これが、IPv4アドレスがなくなり、64ビット時代に入った理由です。

しかし、数231 - 1(2,147,483,647)は、1兆(1,000,000,000,000)数ほど大きくはありません。これは、マシンがクラッシュすることなく正常に表示できるようです。

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

368
Ben Johnson mk2

私はあなたに別の質問をすることによってあなたの質問に答えます:

どのようにあなたは6にあなたの指を頼りにしますか?

片手で可能な限り最大の数までカウントアップした後、指がなくなったらもう片方の手に進みます。コンピュータが同じことをします、彼らが1つのレジスタが保持できるより大きい値を表す必要があるならば、彼らはデータを扱うために複数の32ビットブロックを使うでしょう。

785

32ビット整数が2 ^ 32-1より大きい値を保持できないことが正しいです。ただし、この32ビット整数の値と画面上での表示方法はまったく異なります。印刷文字列 "1000000000000"は、メモリ内の32ビット整数では表されません。

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


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

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

399
Bigbio2002

まず第一に、32ビットコンピュータでは、1台のWordに最大2²2 -1までの数字を格納できますMachine Word は、CPUが自然な方法で処理できるデータの量です(つまり、そのサイズのデータ​​に対する操作はハードウェアで実装され、一般的に最も速く実行されます)。 32ビットCPUは32ビットからなるワードを使用するので、0から2³²-1までの数値を1ワードに格納できます

次に、1兆1000000000000は2つの異なる点です。

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

押すことで 1 何度も  あなたがテキストを入力している12回。 1 1を入力し、  0を入力します。見る?あなたは文字を入力しています。文字は数字ではありません。タイプライターはCPUやメモリをまったく持っておらず、テキストだけなので、彼らはそのような「数字」をうまく処理していました。

1000000000000は数値ではないことの証明:text:1兆を意味します(10進数) )、4096(2進数)または281474976710656(16進数)。それは異なるシステムでさらに多くの意味を持ちます。 1000000000000の意味は数値であり、それを格納することは別の話です(すぐにそれに戻ります)。

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

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

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

それでは、数字の保存に戻りましょう。あふれているテキストと同じように動作しますが、それらは右から左にフィットします。それは複雑に聞こえるかもしれないので、ここに例があります。簡単にするために、次のように仮定しましょう。

  • 私たちの架空のコンピュータはバイナリではなく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

オーバーフローが発生する可能性があり、追加のメモリが必要になる可能性があると予測しました。このように数字を扱うことは、一語に収まる数字ほど速くはなく、ソフトウェアで実装する必要があります。 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進数ではかなりうまくいきます

190
gronostaj

コンピュータがクラッシュすることなく、"THIS STATEMENT IS FALSE"と書くこともできます。@ Scottの答えは、特定の計算フレームワークで注目に値する、しかし、多数を「書く」というあなたの質問は、少なくとも解釈されるまでは、単なるプレーンテキストであることを意味します。

編集:を使って 皮肉が少ない numberをさまざまな方法でより有用な情報をメモリに格納できます。私はこれらをより高い抽象度で記述します。つまり、現代のプログラマは実行のためにマシンコードに変換される前にコードを書いているかもしれません。

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

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

あなたが否定的になりたい場合はどうなりますか?直感的には、符号付き整数がゲームの名前です。慣習は-2^(n-1)から2^(n-1)-1までのすべての値を割り当てることです - このように我々は+0-0を書くために2つの方法を扱わなければならないという混乱を避けます。したがって、32ビット符号付き整数は-2147483648から2147483647までの値を保持します。いいですよね。

わかりました、私達は小数部のない数である整数をカバーしました。非整数部分は01の間のどこかにしかできないので、記述するのに使われる余分なビットはすべて精度を上げるでしょう。1/ 2、1/4、1/8 ...単純分数の0.1を分母に2のべき乗しか持てない分数の合計として正確に表現することはできません。整数として数値を格納する方がはるかに簡単ではないでしょうが、代わりに基数(小数点)を置くことに同意しますか?これは固定小数点numbersと呼ばれます。ここでは1234100を格納しますが、代わりに1234.100として読み取るという規約に同意します。

計算に使用される比較的一般的なタイプはfloating pointです。それが働く方法は本当にきちんとしています、それは符号値を格納するために1ビットを使用してそれから指数と仮数を格納するためにいくつかを使用します。そのような割り当てを定義する標準がありますが、 32ビットfloat の場合、格納できる最大数は圧倒的です。

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

しかし、これは精度を犠牲にしています。ブラウザで利用可能なJavaScriptは64ビット浮動小数点数を使用します、そしてそれはまだ物事を正しくすることができません。これをアドレスバーにコピーしてEnterを押すだけです。ネタバレ警報:結果はnotになります0.3

javascript:alert(0.1+0.2);

Microsoft .NET 4.5の BigInteger のような他の代替型があります。これは理論的には上限も下限もなく、「バッチ」単位で計算する必要があります。しかしおそらくもっと魅力的な技術は、understandmathで、Wolfram Mathematicaエンジンのように、 infinity のような抽象的な値で正確に動作することができます。

40
o.v.

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

確かに、もしコンピュータが単一のWord(32ビットシステムでは4バイト)を使って数字の単純な2進表現を使って数字を保存することを主張するなら、32ビットコンピュータは2 ^ 32までしか数字を保存できません。しかし、それを使って達成したいことに応じて、数値をエンコードする方法は他にもたくさんあります。

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

しかし、さらに精度が必要な場合は、他にも多くの選択肢があります。明らかに、制限なしであなたのエンコーディングにもっと多くの単語を使うことができます(ただし、エンコードされたフォーマットに変換したり、エンコードされたフォーマットから変換するとパフォーマンスが低下します)。これを行うことができる1つの方法を探求したいと思えば計算に数百桁の精度を可能にする符号化方式を使用するExcelのための素晴らしいオープンソースアドインがあります。アドインはXnumbersと呼ばれ、ここで利用可能です。コードはVisual Basicで作成されていますが、これは最速の方法ではありませんが、理解と変更が容易であるという利点があります。コンピュータがどのようにしてより長い数字のエンコードを達成するかを学ぶのは素晴らしい方法です。プログラミングツールをインストールしなくても、Excel内で結果を試すことができます。

31
matt_black

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

紙に好きな数字を書くことができます。白い紙に1兆ドットを書いてみてください。遅くて効果がありません。だからこそ、私たちはそれらの大きな数字を表すための10桁のシステムを持っています。私たちには "million"、 "兆"などのような大きな数字の名前さえあるので、one one one one one one one one one one one...を大声で言ってはいけません。

32ビットプロセッサは、正確に32バイナリ桁の長さのメモリブロックで最も速く効率的に動作するように設計されています。しかし、私たち人間は一般的に10桁の数値システムを使い、コンピュータは電子的なので2桁のシステムを使います( バイナリ )。 32と64という数字はたまたま2のべき乗になります。したがって、100万と1兆もの10のべき乗です。

紙にそれらを書くとき、私たちは大きな数字を数字に分けます。コンピュータは、数字をより大きな桁数に分割します。私達は私達が好むあらゆる数を書き留めることができ、私達がそうそれらを設計すればそうコンピュータもそうするかもしれない。

24
user1306322

32ビットと64ビットはメモリアドレスを表します。あなたのコンピュータのメモリは郵便局の箱のようなもので、それぞれが異なるアドレスを持っています。 CPU(Central Processing Unit)は、これらのアドレスを使用してRAM(Random Access Memory)のメモリ位置をアドレス指定します。 CPUが16ビットアドレスしか扱えない場合は、32MBのRAMしか使用できません(当時は巨大に見えました)。 32ビットでそれは4 +ギガバイト(当時は巨大に見えた)に行きました。 64ビットアドレスがあるので、RAMは数テラバイトになります(これは巨大に見えます)。
しかし、プログラムは、数字やテキストを格納するなどのために複数のメモリブロックを割り当てることができます。これはプログラム次第で、各アドレスのサイズには関係ありません。だからプログラムはCPUに伝えることができる、私は記憶域の10アドレスブロックを使用してから非常に大きな数、または10文字の文字列か何かを保存するつもりだ。
補足:メモリアドレスは「ポインタ」で示されるので、32ビットおよび64ビットの値はメモリにアクセスするために使用されるポインタのサイズを意味します。

15
Engineer

数字の表示は整数ではなく個々の文字を使用して行われるためです。数字の各桁は、使用されるエンコーディングによって定義される整数値を持つ個別の文字リテラルで表されます。例えば、'a'はascii値97で表され、'1'49で表されます。ここで ASCIIテーブルをチェックしてください
'a'と '1'の表示は同じです。それらは整数ではなく文字リテラルです。各文字リテラルは、8ビットまたは1バイトサイズで値を格納する32ビットプラットフォームで最大255の値を持つことが許されているので、それらは一緒にグループ化することができます。表示されます。表示できる文字数は、RAMによって異なります。 1バイトのRAMしかない場合は1文字しか表示できません。1GBのRAMがある場合は1024 * 1024 * 1024文字を表示できます(数学を実行するのが面倒です)。

ただし、この制限は計算にも当てはまりますが、IPV4標準に関心があると思います。それは完全にコンピュータのbit-sizeに関連しているわけではありませんが、それはどういうわけか規格に影響を与えました。 IPV4標準が作成されたとき、彼らは32ビット整数でip値を格納しました。今あなたがサイズを与えたら、そしてそれは標準になりました。私たちがインターネットについて知っていることはすべてそれに依存していました、そしてそれから私たちは割り当てるIPアドレスを使い果たしました。したがって、IP標準が64ビットになるように変更された場合、ルーター(これは正しいと思います)や他のネットワークデバイスを含め、すべてが機能しなくなります。そのため、32ビット整数と128ビット整数を入れ替えた新しい標準を作成する必要があります。そして残りの規格を調整しました。ハードウェアメーカーは、この新しい規格をサポートしていることを宣言するだけでよくなり、それはウイルスになります。それはそれほど単純ではありませんが、私はあなたがここでポイントを得たと思います。

免責事項:ここに記載されている点のほとんどは、私の仮定に当てはまります。簡単にするために、ここで重要な点を見逃した可能性があります。私は数字が得意ではないので、いくつかの数字を逃したにちがいありませんが、ここでの私のポイントは、なぜそれがPCをクラッシュさせないかについてのOPの答えを答えることです。

13
noob

プロセッサでは、「言葉」があります。違う言葉があります。人々が「32ビットプロセッサ」と言うとき、彼らは主に「メモリバス幅」を意味します。このワードは、送信(24ビット)と制御(他のビット)に対応するコンピュータのサブシステムを指す、さまざまな「フィールド」から構成されています。私は正確な数については間違っている可能性があります、マニュアルを通してそれについてあなた自身を確かめてください。

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

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

まとめ:(1)バス幅が計算幅に直接接続されていない、(2)ワードが違う(メモリワード、レジスタワード、バスワードなど)互いに接続しないでください。それ以外の場合は、約8、16、24の約数があります。多くのプロセッサでは6ビットWordを使用していました(ただしその歴史)。

12
sanaris

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

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

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

長年にわたり、プログラマは、単一のプロセッサレジスタまたはメモリアドレスに格納できる数よりも大きい数を格納して処理するために、あらゆる種類のchicaneryを考案しました。多くの方法が存在するが、それらはすべて、それらの「固有の」レジスタ/メモリ位置幅よりも大きい値を格納するために複数のレジスタ/メモリアドレスを使用することを含む。

これらの方法はすべて、マシンが本来の容量よりも大きい値を保存/処理できるという点で有益です。欠点は、ほとんどすべてのアプローチが複数のマシン命令/読み取りなどを必要とすることです。これらの番号を処理します。時折多数の場合、これは問題になりません。 多数の多数(特に大きいメモリアドレス)を扱う場合、オーバーヘッドが発生することで処理が遅くなります。

したがって、レジスタ、メモリ位置、およびメモリアドレスハードウェアを「より広く」かつ「よりネイティブに」取り扱うために最小の操作数でそのような数を処理することができるように広くすることが一般的に望まれている。

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

10
user48420

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

ソフトウェアは、データの受け取り方法、処理方法、保存方法、および他人への提供方法を​​マシンに指示するコードです。

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

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

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

10
Adam Davis

32ビットコンピュータでは、1台のWordに最大2 ^ 32までの数字しか格納できませんが、それでも大きなエンティティデータを処理できないわけではありません。

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

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

通常のIntel 32ビットプロセッサは、内部で128ビットの数字を処理できます。これにより、1000000000000000000000000000000000000000000のような数字を問題なく処理できます。

あなたはコンピュータでそれよりはるかに大きい数を扱うことができます、しかしそれから計算はソフトウェアによってされなければなりません、CPUは128ビットより大きい数を扱うための命令を持っていません。 (それは浮動小数点数の形ではるかに大きい数を扱うことができます、しかしあなたは15桁の精度しか持っていません。)

8
Guffa

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

「32ビット」はメモリアドレス幅を表します。レジスタサイズとは関係ありません。多くの32ビットCPUはおそらく64ビットあるいは128ビットのレジスタを持っています。特にx86製品ラインを参照すると、最近の民生用CPUはすべて64ビットであり、特別な目的のために256ビットまでのレジスタを所有している。

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

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

どんな大きさのレジスタでも、より大きな数でを計算することができる理由は、大きすぎる計算が分割される可能性があるからです。レジスタに収まるようにいくつかの小さなものにまとめられます(実際にはほんの少し複雑です)。

6
mafu

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

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

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

明示的に:

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

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

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

6
Kyle Strand

典型的な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);

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

mpz_tの構造は、Scott Chamberlainが両手を使って6を数える例とまったく同じです。これは基本的にはマシンWordサイズのmp_limb_tタイプの配列であり、数値がマシンWordに収まるには大きすぎる場合、GMPは複数のmp_limb_tを使用して数値の上位/下位部分を格納します。

5
Animism

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

整数型番号:この表は要点を説明するのに役立ちます( http://msdn.Microsoft.com/ja-jp/library/ 296az74e.aspx )。これはC++の限界に影響を与えます。例えば、Int64タイプ番号には、-9223372036854775808から9223372036854775807までの範囲があります。

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

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

5
Dee

あなたの心の中であなたは10の異なる数字しか知りません。 0から9。あなたの脳の内部では、これは確かにコンピュータとは違った方法でエンコードされています。

コンピュータはビットを使って数字をエンコードしますが、それは重要ではありません。それはエンジニアがものをエンコードすることを選んだ方法ですが、あなたはそれを無視するべきです。私たち人間は10の異なる値のためのユニークな表現を持っていますが、32ビットのコンピューターは40億以上の異なる値のユニークな表現を持っているとあなたは考えることができます。

もっと大きな数を理解しなければならないときはいつでも、私たちはシステムを使います。一番左の数字が最も重要です。それは次の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個の異なる記号を持っていることを除いて、コンピュータはそれを全く同じ方法でやる。

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

最後に、コンピュータは任意の数字を単純な文字の並びとして表示することができます。それこそがコンピュータが得意なことです。一連の文字と内部表現との間の変換を行うためのアルゴリズムは非常に複雑です。

5
frodeborli

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

3
Rolf

この答えの内容の大部分はもともと this answer から来たものです(その他の質問が重複としてマークされる前に書かれています)。それで私は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
a.k.a:
0x4082xxxxD7
さて、それをあなたのために解釈させてください。
0xは、後続の数字が16進数であることを意味します。
「40」について、もう少し詳しく説明します。
82は "A"レジスタの一部で、一連の8ビットです。
xxとxxは、 "B"レジスタと "C"レジスタという名前の他の2つのレジスタの一部です。これらのビットを0または1で埋めなかったのは、 "CPUに送信された" ADD "命令によって、命令によってこれらのビットが変更されない可能性があるためです。いくつかのフラグビットを除いて、変更されます。
D7は「D」レジスタと呼ばれる、より多くのビットに収まります。
レジスタは単なるメモリです。レジスタはCPUに組み込まれているため、CPUはRAMスティック上のメモリと対話することなくレジスタにアクセスできます。

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

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

各CPU命令には、アセンブリをプログラムする人が使用する文書がいくつかあります。その文書では、各命令でどのレジスタを使用するかを指定する必要があります。 (したがって、どのレジスタを使用するかの選択は、アセンブリ言語プログラマではなく、CPUの設計者によってしばしば指定されます。ただし、ある程度の柔軟性がある場合もあります。)

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

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

(あなたが望んだ結果に収まらないほど引き算が小さすぎる場合のために、一般的に "アンダーフロー"フラグもあります。)

どれだけ複雑なことが起こったのかを示すためだけに:
Intel 4004は4ビットCPUでした
[800] Intel 8008は8ビットCPUだった。 A、B、C、Dという8ビットレジスタがあります。
Intel 8086は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レジスタを構成するビットの半分であり、EAXレジスタを構成するビットの半分は、RAXレジスタを構成するビットの半分です。つまり、AXの値を変更したときはいつでも、EAXとRAXも変更していることになります。これは、AXで使用されるビットはRAXで使用されるビットの一部だからです。 (65,536の倍数である値でEAXを変更しても、下位16ビットは変更されないため、AXは変更されません。65,536の倍数ではない値でEAXを変更すると、AXにも影響があります。 。)

私が述べたものよりも多くのフラグとレジスタがあります。私は単純な概念的な例を提供するために単に一般的に使用されるものを選びました。

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

0
TOOGAM