32ビットコンピュータは231 – 1までの符号付き整数しか格納できません。 これがIPv4アドレスを使い果たし、64ビットの時代に突入した理由です
しかし、231 – 1(2,147,483,647)という数字は、私のマシンがクラッシュすることなく正常に表示できているように見える1兆(1,000,000,000,000)ほどではありません
誰か理由を説明してくれませんか?
370 community wiki None
あなたの質問には別の質問をして答えています
指で6まで数えるには?
あなたは片手で可能な限り最大の数まで数え、指が足りなくなったらもう片方の手に移動します。コンピュータも同じことをしていますが、1つのレジスタが保持できる値よりも大きな値を表現する必要がある場合は、データを扱うために複数の32ビットブロックを使用します
789 community wiki 2014-01-08
32 ビット整数は 2^32-1 よりも大きな値を持つことはできません。しかし、この32ビット整数の値と、それが画面にどのように表示されるかは、全く別のものです。印刷された文字列「1000000000000」は、メモリ上では32ビット整数で表現されていません
文字通り “1000000000000 “という数字を表示するには、13 バイトのメモリが必要です。各バイトは最大 255 までの値を保持することができます。それらのどれもが全体の数値を保持することはできませんが、ASCII 文字として個別に解釈することで (例えば、文字 ‘0
‘ は 10 進数値 48、2 進数値 00110000
で表されます)、人間にとって意味のあるフォーマットにまとめることができます
プログラミングにおける関連する概念にタイプキャスティングというものがあります。上の例のように、これは数値として解釈されたり、文字として解釈されたり、あるいは全く別のものとして解釈されたりします。32 ビット整数は 1000000000000 の値を保持できないかもしれませんが、32 ビット浮動小数点数は全く異なる解釈で保持できます
コンピュータが内部で大きな数をどのように処理するかについては、64ビット整数(160億までの値に対応)や浮動小数点値、任意の大きな数を処理するための専用のライブラリなどがあります
395 community wiki 2014-01-08
何よりもまず、32ビットコンピュータは、1つのマシンワードに2³²-1までの数字を格納することができます。マシンワードとは、CPUが自然な形で処理できるデータ量のことである(つまり、その大きさのデータに対する演算はハードウェアで実装されており、一般的には最速で実行できる)。32ビットCPUは32ビットで構成されたワードを使用しているため、1つのワードに0から2³²-1までの数字を格納することができます
第二に、1兆と100000000は別物です
- 1兆というのは数の抽象的な概念です
- 1000000000000はテキストです
1を1回押した後、0を12回押すことで、テキストを入力していることになります。1 は 1
と入力し、0 は 0
と入力します。ほらね。あなたは文字を入力しています。文字は数字ではありません。タイプライターはCPUもメモリも全く持ってなくて、そんな「数字」をかなりうまく扱っていたんだよ、ただのテキストなんだから
1000000000000は数字ではなくテキストであることを証明します:1兆(10進数)、4096(2進数)、281474976710656(16進数)を意味します。それは異なるシステムでさらに多くの意味を持っています。1000000000000の意味は数字であり、それを格納することは別の話です(すぐにそれに戻ります)
テキスト(プログラミングでは文字列と呼ばれています)を1000000000000000000に格納するには、14バイト(各文字に1バイト、基本的には「文字列はここで終わる」という意味の終端NULLバイト)が必要です。これは4つのマシンワードです。3と5分の1でも十分ですが、私が言ったように、マシンワードでの演算が一番速いです。ASCIIがテキストの保存に使われているとすると、メモリ上では次のようになります: (0
と1
に対応するASCIIコードをバイナリに変換し、それぞれの単語を別の行にまとめます)
00110001 00110000 00110000 00110000
00110000 00110000 00110000 00110000
00110000 00110000 00110000 00110000
00110000 00000000 00000000 00000000
1 つの単語に 4 文字が収まると、残りの文字は次の単語に移動します。残りはすべて(最初のNULLバイトを含む)が収まるまで次のワードに移動されます
さて、数字の格納に戻ります。文字がはみ出しているときと同じように動作しますが、右から左へとはめ込んでいきます。複雑に聞こえるかもしれませんが、例を挙げてみましょう。簡単のために、以下のように仮定してみましょう
- 私たちの想像上のコンピュータは、2進数の代わりに10進数を使用しています
- 1バイトに数字
0..9
を格納することができます - 1 つの単語は 2 バイトで構成されています
ここに空の2ワードメモリがあります
0 0
0 0
4という数字を収納してみましょう
0 4
0 0
今度は9を追加してみましょう
1 3
0 0
両方のオペランドは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 community wiki 2018-04-15
あなたのコンピュータがクラッシュすることなく、”THIS STATEMENT IS FALSE “と書くこともできます。)スコットさんの答えは、特定の計算フレームワークにはぴったりですが、大きな数字を「書く」というあなたの質問は、少なくともそれが解釈されるまでは、それがただのテキストであることを示唆しています
編集: 数値がメモリに格納されるさまざまな方法について、より有用な情報を less sarcasmithime と共に提供しています。私はこれらをより高い抽象度、つまり現代のプログラマーが実行のためにマシンコードに翻訳される前にコードを書いているかもしれない用語で説明します
コンピュータ上のデータは特定の型に制限されなければならず、そのような型のコンピュータ定義は、このデータに対してどのような操作がどのように実行できるかを説明します(例:数値の比較、テキストの連結、ブール値のXOR)。数値にテキストを単純に追加することはできませんが、数値にテキストを乗算することができないのと同じように、これらの値のいくつかは型の間で変換することができます
符号なし整数から始めましょう。これらの値型では、すべてのビットが桁に関する情報を格納するために使用されます。あなたのは、0
から2^32-1
までの任意の値を格納することができる32ビット符号なし整数の例です。そしてはい、使用されるプラットホームの言語か建築によって 16 ビットの整数か 256 ビットの整数を持つことができます
負の値を取りたい場合は?直感的には、符号付き整数がゲームの名前です。慣習として、-2^(n-1)
から2^(n-1)-1
までのすべての値を割り当てることになっています – この方法では、+0
と-0
の2つの書き方を扱う必要があるという混乱を避けることができます。つまり、32ビット符号付き整数は-2147483648
から2147483647
までの値を保持することになります。すっきりしていますね
さて、ここまで整数とは小数点以下の要素を持たない数値のことです。非整数の部分は 0
と 1
の間のどこかにしか表現できないので、それを表現するために余分なビットが使われるたびに精度が上がります: 1/2, 1/4, 1/8…問題は、単純な 10 進数 0.1
を分母に 2 の累乗しか持てない分数の和として正確に表現できないことです。整数として格納しつつ、代わりに基数(小数点)を置くことに同意した方がはるかに簡単ではないでしょうか?これは固定小数点数と呼ばれるもので、1234100
を格納しているが、代わりに1234.100
と読むことに同意しています
計算に使われる比較的一般的な型は floating point
です。これは、符号値を格納するために1ビットを使用し、その後、指数と記号を格納するためにいくつかのビットを使用します。このような割り当てを定義する標準がありますが、32ビットのfloatでは、格納できる最大数は圧倒的です
(2 - 2^-23) * 2^(2^7 - 1) ≈ 3.4 * 10^38
しかし、これは精度を犠牲にしています。ブラウザで利用できるJavaScriptは64ビットのフロートを使用していますが、それでもうまくいかないのです。これをアドレスバーにコピーしてエンターキーを押すだけです。ネタバレ注意: 結果は 0.3
にはなりません
javascript:alert(0.1+0.2);
Microsoft .NET 4.5のBigInteger
のように,理論的には上限も下限もなく,「バッチ」で計算しなければならない代替型もありますが,おそらくもっと魅力的なテクノロジーは,infinityのような抽象値を正確に扱うことができるWolfram Mathematica エンジンのような数学を理解しているテクノロジーです.
40 community wiki 2014-01-08
重要なのは、コンピュータがどのように数字を符号化するかを理解することです
確かに、コンピュータが1つの単語(32ビットシステムでは4バイト)を使った数字の単純な2進表現を使って数字を格納することにこだわるなら、32ビットコンピュータは2^32までの数字しか格納できません。しかし、数字をエンコードする方法は、あなたがそれらで何を達成したいかに応じて、他にもたくさんあります
一つの例として、コンピュータが浮動小数点数を格納する方法があります。コンピュータはそれらをエンコードするために、さまざまな方法を使うことができます。IEEE 754は、2^32よりも大きな数値をエンコードするための規則を定義しています。ざっくり言うと、コンピュータは32ビットを数字のいくつかの桁を表す部分と、数字の大きさを表す他のビットに分割することで、これを実装することができます(すなわち、指数、10^x)。これにより、大きさの面ではより大きな範囲の数値を扱えるようになりますが、精度が低下してしまいます(これは多くの目的には問題ありません)。もちろん、コンピュータはこのエンコーディングに複数の単語を使うこともでき、利用可能なエンコーディングされた数値の大きさの精度を高めることができます。IEEE 標準の単純な 10 進 32 バージョンでは、10 進数で約 7 桁の精度の数字と 10^96 程度までの大きさの数字を使用できます
しかし、余分な精度が必要な場合は、他にも多くのオプションがあります。明らかに、エンコーディングには制限なくより多くの単語を使用することができます(ただし、エンコーディングされたフォーマットへの変換とエンコーディングされたフォーマットからの変換にはパフォーマンス上のペナルティがあります)。これを行う方法の一つとして、数百桁の精度の計算を可能にするエンコーディングスキームを使用したExcel用の素晴らしいオープンソースのアドインがあります。アドインはXnumbersと呼ばれ、こちらから入手できます。コードはVisual Basicで書かれていますが、最速ではありませんが、理解しやすく修正しやすいという利点があります。コンピュータがどのようにして長い数字のエンコーディングを実現しているのかを学ぶには最適な方法です。また、プログラミングツールをインストールしなくても、Excel内で結果を弄ることができます
31 community wiki 2014-01-08
質問に書いてあります
紙に好きな数字を書くことができます。白い紙に1兆個のドットを書いてみてください。それは遅いし、効果がない。だからこそ、私たちは10桁の数字を使って大きな数字を表現しているのです。百万」「兆」などの大きな数字には名前までつけているので、one one one one one one one one one one one...
と声に出して言うことはありません
32ビットプロセッサは、正確に32桁の2進数の長さのメモリのブロックで最も迅速かつ効率的に動作するように設計されています。しかし、私たち人間は、一般的に10桁の数字システムを使用し、コンピュータは、電子的であることから、2桁のシステムを使用しています(バイナリー)。32と64という数字はたまたま2のべき乗であり、100万と1兆は10のべき乗である。これらの数を使って操作するのは、例えば65536の多乗よりも簡単です
私たちは紙に書くときに大きな数字を桁に分解します。コンピュータは数字をより大きな桁数に分解します。私たちは好きな数字を好きなように書くことができます そして私たちがそのように設計すれば コンピュータもそうなるかもしれません
24 community wiki 2014-01-11
32bitと64bitはメモリのアドレスを指します。コンピュータのメモリは郵便局の箱のようなもので、それぞれに異なるアドレスを持っています。CPU (Central Processing Unit) はこれらのアドレスを使用して RAM (Random Access Memory) 上のメモリの位置をアドレスします。CPUが16ビットのアドレスしか扱えなかった頃は、32mbのRAMしか使えませんでした(当時は巨大に見えました)。32bitになると4+gbになりました(当時は巨大に見えました)。今では64bitアドレスを扱うようになったので、RAMはテラバイトになりました(当時は巨大に思えました)。 しかし、プログラムは数字やテキストを格納するために複数のメモリブロックを割り当てることができますが、これはプログラム次第であり、各アドレスのサイズには関係ありません。つまり、プログラムはCPUに「10個のアドレスブロックのストレージを使用して、非常に大きな数字や10文字の文字列などを保存したい」と伝えることができるのです。 余談: メモリのアドレスは「ポインタ」によって指し示されるので、32 ビットと 64 ビットの値は、メモリにアクセスするために使用されるポインタのサイズを意味します。
15 community wiki 2014-01-08
なぜなら、数値の表示は整数ではなく個々の文字を使って行われるからです。数字の各桁は個別の文字リテラルで表現され、その整数値は使用するエンコーディングによって定義されます。例えば 'a'
はアスキー値 97
で表現され、'1'
は 49
で表現されます。ascii テーブルはこちら a’ と ‘1’ の表示は同じです。これらは文字リテラルであり、整数ではありません。それぞれの文字リテラルは、32ビットプラットフォームでは最大255の値を持つことが許されており、8ビットまたは1バイトのサイズで値を格納します(プラットフォームに依存しますが、8ビットが最も一般的な文字サイズです)。どのくらいの分離した文字を表示できるかは、あなたが持っているRAMに依存します。あなたがちょうど1バイトのRAMを持っている場合は、1文字だけを表示することができ、あなたが1GBのRAMを持っている場合は、よく1024*1024*1024文字を表示することができます(計算を行うには怠惰すぎる)
この制限は、しかし計算には適用されますが、IPV4規格のことが気になるのでしょうね。コンピュータのbit-size
とは全く関係ありませんが、何らかの形で規格に影響を与えています。IPV4標準が作られたとき、IPの値は32ビットの整数で格納されていました。今では、一度サイズを指定すると、それが標準になりました。インターネットについて知っていることはすべてそれに依存していたので、割り当てられるIPアドレスがなくなってしまったのです。ですから、もしIP標準が64ビットに改定されたら、ルータ(これは正しいと思います)や他のネットワーク機器も含めて、すべてのものが動かなくなってしまいます。そこで、32ビットの整数を128ビットの整数に入れ替えた新しい規格を作らなければなりません。そして、標準の残りの部分を調整しました。ハードウェアメーカーは、この新規格をサポートしていることを宣言するだけで、それはウイルスを取得します。そんなに単純な話ではないが、ここまでで要点がわかっただろう
免責事項:ここで述べたポイントのほとんどは、私の思い込みに基づくものです。簡単にするために重要なポイントを見逃しているかもしれません。私は数字が苦手なので、数字を見落としているかもしれませんが、ここでの私のポイントは、なぜPCがクラッシュしないのかというOPの回答に答えることです
13 community wiki 2014-01-08
プロセッサーには「言葉」があります。いろいろな言葉があります。人々が「32ビットプロセッサ」と言うとき、彼らはほとんどの場合、「メモリバス幅」を意味します。この言葉は、送信(24ビット)と制御(他のビット)に対応するコンピュータのサブシステムを指す異なる「フィールド」で構成されています。私は正確な数字について間違っていることができます、マニュアルを介してそれについて自分自身を確認してください
全く別の側面は計算です。SSEとMMXの命令セットは長い整数を格納することができます。生産性を損なわない最大の長さは、現在のSSEのバージョンにもよりますが、常に64ビットの倍数程度です
現在のOpteronプロセッサは256ビット幅の数値を扱うことができます(整数はよくわかりませんが、floatは確実です)
要約:(1)バス幅と演算幅は直接は関係ない。(2)メモリワード、レジスタワード、バスワードなどの異なるワードであっても、8や16、24などの共通の除数を持っていれば、お互いには関係ない。多くのプロセッサは、6ビットのワードを使っていました(しかし、その歴史はあります)
13 community wiki 2014-01-08
コンピューティングデバイスの目的は、一般的に、データを受け入れ、処理し、保存し、放出することです。基盤となるハードウェアは、これら4つの機能を実行するのに役立つマシンにすぎません。ソフトウェアなしでは、これらの機能のどれも行うことができません
ソフトウェアとは、データをどのように受け入れ、どのように処理し、どのように保存し、どのように他の人に提供するかを機械に伝えるコードのことです
基盤となるハードウェアには常に限界があります。32ビットマシンの場合、データを処理するレジスタのほとんどは32ビット幅しかありません。これは、マシンが2^32を超える数を扱えないという意味ではありませんが、より大きな数を扱いたい場合には、マシンがそれを受け入れ、処理し、保存し、放出するのに1サイクル以上かかる可能性があるということを意味しています
ソフトウェアは、マシンに数字をどのように扱うかを指示します。ソフトウェアが大きな数字を扱うように設計されている場合、より大きな数字をどのように扱うかを伝える一連の命令をCPUに送ります。例えば、あなたの数字は2つの32ビットレジスタで表すことができます。1,234個の数字を加算したい場合、ソフトウェアはCPUに、まず1,234個の数字を下位レジスタに加算し、オーバーフロービットをチェックして、下位レジスタには大きすぎる数字が加算されていないかどうかを確認するように指示します。もしそうであれば、上位レジスタに1を加算します
小学生がキャリーを使って足し算をするように教えられているのと同じように、CPUは1つのレジスタに保持できる数よりも大きな数を扱うように教えられることがあります。これは、ほとんどの一般的な数学演算で、実用的な大きさの数値に当てはまります
10 community wiki 2014-01-08
この違いは、コンピュータにデータを保存する方法にあります
理論上の8ビットマシンでは、1つのプロセッサレジスタまたはメモリアドレスに2^8個の値を格納することしかできません。(これは、使用されているプロセッサやメモリアーキテクチャなどに基づいて、「マシン」から「マシン」へと変化することを覚えておいてください。しかし、今のところは、仮想的な「ステレオタイプ」のマシンに固執してみましょう)
理論上16ビットマシンの場合、レジスタ/メモリの最大値は2^16、32ビットマシンの場合は2^32などとなります
長年にわたり、プログラマーは、1つのプロセッサのレジスタやメモリアドレスに格納できる以上の数値を格納したり処理したりするために、あらゆる種類の奇抜な方法を考案してきました。多くの方法が存在しますが、すべての方法では、複数のレジスタ/メモリアドレスを使用して、「ネイティブ」レジスタ/メモリの位置の幅よりも大きな値を格納する必要があります
これらの方法はすべて、マシンが本来の容量よりも大きな値を保存/処理できるという点でメリットがあります。欠点は、ほとんどすべてのアプローチが、これらの数値を処理するために複数のマシン命令/読み取り/などを必要とすることです。たまに大きな値を扱う場合には、これは問題ではありません。たくさんの大きな数値(特に大きなメモリアドレス)を扱う場合は、オーバーヘッドのために処理が遅くなります
したがって、レジスタ、メモリロケーション、メモリアドレスのハードウェアを「広く」「広く」「広く」して、大きな数を「ネイティブに」扱うようにして、そのような数を最小の操作数で扱えるようにしたいという一般的な願望があるのです
数のサイズが無限大なので、プロセッサのレジスタ/メモリサイズ/アドレスは常にネイティブ数のサイズと、より大きな幅を実装するためのコストのバランスをとっています
10 community wiki 2014-01-09
32ビットコンピュータは、1つのマシンワードに2^32までの数字しか格納できませんが、それよりも大きなデータの実体を扱えないわけではありません
32ビットコンピュータの意味は、一般的にデータバスとアドレスバスの幅が32ビットであるため、一度に4GBのメモリアドレス空間を扱うことができ、データバスを介して一度に4バイトのデータを送ることができるということです
しかし、それはコンピュータがより多くのデータを扱うことを制限するものではなく、データバス上で送信されるときにデータを4バイトのチャンクに分割しなければならないだけです
通常のインテル32ビットプロセッサは、内部的に128ビットの数字を扱うことができるので、何の問題もなく1000000000000000000000000000000のような数字を扱うことができます
コンピュータではそれよりもはるかに大きな数字を扱うことができますが,計算はソフトウェアで行わなければならず,CPUには128ビットよりも大きな数字を扱うための命令がありません.(それは浮動小数点数の形ではるかに大きな数を扱うことができますが、その後、あなたは15桁の精度しか持っていません)
8 community wiki 2014-01-09
この質問ではかなり重要な事実であるため、他の多くの回答にメモを追加するだけで、見逃しています
“32ビット “とは、メモリアドレスの幅のことです。レジスタサイズとは関係ありません。32ビットCPUの多くは64ビット、あるいは128ビットのレジスタを持っている可能性が高い。特にx86の製品ラインを参照すると、最近のコンシューマ向けCPUはすべて64bitで、特殊な目的のために256bitまでのレジスタを持っています
このレジスタ幅とアドレス幅の違いは、4ビットのレジスタと8ビットのアドレスを持っていた古代から存在していましたし、その逆もあります
他の回答で説明したように、レジスターの大きさに関係なく、大きな数字を格納しても問題ないことは簡単にわかります
レジスターが、どんなサイズであっても、さらに大きな数値で計算できるのは、大きすぎる計算を、レジスターに収まるいくつかの小さな計算に分解できるからです(実際にはもう少し複雑なだけです)
6 community wiki 2014-01-10
すでに提示されている回答は、実際にはかなり良いものですが、異なる側面から問題に取り組む傾向があり、その結果、不完全な絵を提示しています。また、私の考えでは、彼らはまた、少し過剰に技術的である
だから、他の回答では示唆されているが明確に表現されていないことを明確にするために、問題の核心だと思います
あなたの質問にはいくつかの概念が混ざっていますが、そのうちの一つ(「32ビット」)は、実際には様々な異なるものを指すことができます(そして、異なる回答は異なる解釈を想定しています)。これらの概念はすべて、様々なコンピューティングのコンテキストで使用される(または利用可能な)ビット数(1と0)に関係しています(これが何を意味するかは、以下の例で明らかになることを期待しています)が、概念はそれ以外では無関係です
Explicitly:
- “IPv4/6 “とは、internet protocolのことで、インターネット上で情報がどのようにパッケージ化され、解釈されるかを定義する一連のルールを指します。IPv4とIPv6の主な(または少なくとも最もよく知られている)違いは、アドレス空間(すなわち、ネットワーク上の異なる場所を区別するために使用できるアドレスのセット)がIPv6の方が大きいということです。これは、ネットワークを介して送信されるデータの各パケット内のビット数が、パケットの送信者と受信者を識別するために割り当てられている(つまり、目的のために脇に設定されている)ことに関係しています
- 非コンピューティングの例え。それぞれのパケットはカタツムリメールで送られてくる手紙のようなもので、宛名スペースは封筒に宛名と返信用のアドレスを書くときに「許される」文字数のようなものです
- これまでの他の回答には、このようなことは書かれていませんでした
- コンピュータメモリの “ワード”(32ビットと64ビット)は、一般的にコンピュータが使用する、または “考える “データの最小の部分として考えることができます。これらのデータのビットは、テキストの塊やより大きな整数などのデータの他のビットを構成するために一緒に来る
- 非コンピューティングのアナロジー:言葉は、紙の上で言葉を構成している文字のように少し考えることができますし、思考の列車の中で個々の単語としても考えることができます
- グッファの回答、サナリスの回答、guronostajの回答の最初の段落を参照してください
- 32 ビットのポインタは、単語であってもそうでなくても、原子的に扱われます(つまり、より小さな構成要素に分解できない個々の単位として)。ポインタは、コンピュータが任意のデータの塊のメモリ内の位置を記録するための最低レベルの方法です。コンピュータが使用する(実際にはオペレーティングシステムが使用する)ポインタのサイズによって、1つのポインタでアクセスできるメモリの範囲が制限されていることに注意してください。これは、IPv4が可能なインターネットアドレスの範囲を制限する方法と類似していますが、例えば特定のウェブページに存在することができるデータの量を制限するものではありません。しかし、ポインタのサイズは、ポインタが指すことができるデータ自体のサイズを制限するものではありません。(データサイズがポインタの範囲を超えることを許容するスキームの例については、Linux の inode ポインタ構造 を参照してください。ポインタは通常、ハードドライブ領域ではなくランダムアクセスメモリへのポインタを指すので、これは一般的な「ポインタ」という言葉の使い方とは少し異なることに注意してください)
- 非コンピューティングの類推: hmmmmmm….これはちょっと厄介だな。おそらく、図書館資料の索引付けのためのデューイ十進法は少し似ているのではないでしょうか?あるいは、どんな索引付けシステムでも、本当にそうです
- SiteNookの回答を参照してください
- 上記のポインターに関する私の説明は、いくつかの微妙な詳細を省略したものであり、議論の余地なく完全に正しいとは言えないことに注意してください。しかし、プログラマが直接ポインタを使って作業をするプログラミング言語では、私が描いたような精神的なモードで十分に実用に耐えることができます
- コンピュータが「表示できる」数字は、コンピュータのハードウェアやオペレーティングシステムによって制限されるものではありません
- 非コンピューティングの類推:紙に書くこと
- user1306322 の回答 と Bigbio2002 の回答 を参照してください
これは、”32ビット “というフレーズの解釈の包括的なリストを意図したものではないことに注意してください
余分なクレジット: 数字とコンピュータメモリの原始的な塊の間の素朴な哲学的区別を本当に見るには、チューリングマシンについて少し読んでみてください
6 community wiki 2017-09-06
例えば電卓で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 (large double)は最大指数が308なので、9.999 x 10^308
を入力したり、結果の数として持つことができますが、理論的には308(+1)桁の9
が得られますが、最も重要な15桁だけがそれを表現するために使用され、残りは失われます
さらに、異なるプログラミング言語があり、数値制限の実装が異なる可能性があります。そのため、特殊なアプリケーションであれば、C++よりもはるかに大きな(および/またはより正確/正確な)数値を扱うことができることが想像できます
5 community wiki 2014-01-09
典型的な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 community wiki 2014-01-11
あなたの頭の中では10桁の数字しか知らない。0から9まで脳内では確かにコンピュータとは違った形で 符号化されています
コンピュータはビットを使って数字を符号化していますが、それは重要ではありません。それは技術者がエンコードする方法を選んだだけですが、それは無視した方がいいです。32ビットのコンピュータは40億以上の異なる値を独自に表現しているのに対し、私たち人間は10の異なる値を独自に表現していると考えることができます
より大きな数を理解しなければならない時には必ずシステムを使う。一番左の数字が最も重要である。それは次の数字の10倍の重要性を持っている
40億の異なる値を区別することができるコンピュータは,同じように,値の集合の中で一番左の値を,その集合の次の値の40億倍の重要性を持つようにしなければなりません.実際には、コンピュータは全く気にしません。数字に「重要度」を割り当てることはしない。プログラマーはそのための特別なコードを作らなければなりません
人間の心の中にある固有の記号の数である9よりも大きな値になるたびに、左の数字に1を足していくのです
3+3=6
この場合でも、番号は1つの「スロット」に収まります
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.
追加する数字がなくなったので、オーバーフローフラグが上がったのでスロットを作成して1を挿入するだけです
1308
コンピュータは、人間のように10個しかないのではなく、2^32個、あるいは2^64個の異なる記号を持つことを除いては、全く同じことをします
ハードウェアレベルでは、コンピュータは全く同じ方法でシングルビットで動作します。幸いなことに、それはプログラマにとっては抽象化されています。ビットは2桁しかありません、なぜならそれは電力線で表現するのが簡単だからです。ライトが点灯しているか、または消灯しているかのどちらかです
最後に、コンピュータはどんな数字でも単純な文字の羅列として表示することができました。それがコンピュータの得意とするところです。文字列と内部表現を変換するアルゴリズムは 非常に複雑です
5 community wiki 2014-01-11
なぜなら、あなたが表示しているのは数字ではなく、文字列、または数字の羅列だからです。確かに、数字を扱うアプリ(電卓のようなものだと思いますが)の中には、このような数字を扱えるものもありますね。どんなトリックを使っているのかは知りませんが…。私は他の、もっと凝った回答のいくつかがそれをカバーしていると確信しています
3 community wiki 2014-01-12
この回答の内容のほとんどは、元々この回答(他の質問が重複しているとマークされる前に書かれたもの)から来ています。ですから、私は8ビットの値を使って議論しています(この質問では32ビットの値について質問されていますが)が、8ビットの値の方が概念的に理解するのが簡単で、同じ概念が32ビットの算術のような大きな値にも適用されるので、それで構いません
8ビットである2つの数字を足し算すると、得られる最大の数字は(0xFF + 0xFF = 1FE)になります。実際、8ビットである2つの数字を掛け合わせた場合、得られる最大の数字(0xFF * 0xFF = 0xFE01)は、8ビットの2倍の16ビットのままです
さて、あなたは、xビットプロセッサはxビットしか記録できないと思い込んでいるかもしれません(例えば、8ビットプロセッサは8ビットしか記録できません)。例えば、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 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 “の話に戻ります:これは一連のビットで、しばしば “フラグレジスタ “と呼ばれます。フラグレジスタの各ビットには名前がついています。例えば、「オーバーフロー」ビットがあり、結果が1バイトの結果を格納できるスペースよりも大きい場合にCPUが設定することができます。(この「オーバーフロー」ビットは、しばしば「OF」という略称で呼ばれることがあります。これはゼロではなく、大文字の o です)。ソフトウェアはこのフラグの値をチェックして「問題」に気づくことができます。このビットを使って作業することは、多くの場合、上位レベルの言語では目に見えないように処理されるので、初心者のプログラマは、CPUフラグとの相互作用の仕方について学習しないことが多いです。しかし、アセンブリプログラマは、これらのフラグのいくつかに、他の変数と非常に類似した方法でアクセスするのが一般的かもしれません
例えば、複数のADD命令があるかもしれません。あるADD命令は16ビットの結果をAレジスタとDレジスタに格納し、別の命令は8つの下位ビットをAレジスタに格納し、Dレジスタを無視し、オーバーフロー・ビットを指定します。その後、後で(Aレジスタの結果をメインRAMに格納した後)、8ビットの上位ビットだけをレジスタ(おそらくAレジスタ)に格納する別のADD命令を使用することができます。オーバーフロー・フラグを使用する必要があるかどうかは、どのような乗算命令を使用するかによって異なります
(一般的には「アンダーフロー」というフラグもあり、希望する結果に収まりきらないほどの引き算をした場合に備えています)
どれだけ複雑になったかというと インテル 4004 は 4 ビット CPU で、インテル 8008 は 8 ビット CPU で、A、B、C、D という 8 ビットのレジスタを持っていました。Intel 8086 は 16 ビット CPU で、AX、BX、CX、DX という 16 ビットのレジスタを持っていました。AX、BX、CX、およびDXという名前の16ビットレジスタを持っていました。 Intel 80386 は 32 ビット CPU で、EAX という名前の 32 ビット・レジスタを搭載しています。EAX、EBX、ECX、EDX という名前の 32 ビットレジスタを搭載していました。 Intel x64 CPUはRAX、RBX、RCX、RDXという名前の64ビットレジスタを持っていた。x64 チップは 16 ビットのコードを実行することができ (一部の動作モードでは)、16 ビット命令を解釈することができます。その際、AXレジスタを構成するビットは、EAXレジスタを構成するビットの半分であり、RAXレジスタを構成するビットの半分である。つまり、AXの値を変更するたびに、EAXとRAXも変更することになります(AXで使用するビットはRAXで使用するビットの一部であるため)。(EAXを65,536の倍数の値で変更した場合、下位16ビットは変更されないのでAXは変更されません。の倍数でない値で EAX を変更した場合は、AX にも影響を与えます)
フラグとレジスタは、これまでに述べたものだけではありません。簡単な概念的な例を提供するために、一般的に使われているものをいくつか選んでみました
さて、8ビットCPUの場合、メモリに書き込むときに、4ビットや16ビットのアドレスではなく、8ビットのアドレスを参照できるという制約があるかもしれません。詳細はCPUによって異なりますが、このような制約がある場合は、CPUが8ビットのワードを扱っている可能性があるので、”8ビットCPU “と呼ばれるのが一般的な理由です
0 community wiki 2016-12-30