2014-01-07 20:18:51 +0000 2014-01-07 20:18:51 +0000
369
369
Advertisement

32ビットマシンが2^32までの数字しか扱えないのであれば、なぜマシンがクラッシュせずに1000000000000(兆)を書けるのか

Advertisement

32ビットマシンは231 - 1までの符号付き整数しか格納できません。 IPv4アドレスを使い果たして64ビットの時代に突入したのはこのためです。

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

その理由を誰か説明していただけますか?

Advertisement

回答 (18)

784
784
784
2014-01-07 20:31:38 +0000

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

どのようにあなたの指で6に数えるのですか?

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

395
395
395
2014-01-07 20:36:34 +0000

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

文字通り数字 "1000000000000 "を表示するには13バイトのメモリが必要です。各バイトは最大255までの値を保持することができます。しかし、ASCII 文字として個別に解釈すれば(例えば、文字 ‘0’ は 10 進数 48、2 進数 00110000 で表されます)、人間にとって意味のあるフォーマットにまとめることができます。


プログラミングにおける関連する概念に typecasting があります。上の例のように、それは数値、文字、または完全に何か他のものとして解釈することができます。32 ビット整数は 1000000000000 の値を保持できないかもしれませんが、32 ビット浮動小数点数は全く異なる解釈で保持できます。

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

190
Advertisement
190
190
2014-01-07 21:37:16 +0000

何よりもまず、32ビットコンピュータは、2³²-1までの数字を1つのマシンワードに格納することができます。マシンワード](https://en.wikipedia.org/wiki/Machine_word)とは、CPUが自然に処理できるデータ量のことです(つまり、その大きさのデータに対する演算はハードウェアで実装されており、一般的には最も高速に処理できる)。32ビットCPUは32ビットで構成されたワードを使用するので、0から2³²-1までの数字を1つのワードに格納することができます。

第二に、1兆1000000000000は違うものです。1は1を入力し、0は0を入力します。見ての通りですね。文字を入力しているんです。文字は数字ではありません。タイプライターはCPUやメモリを全く持っていなかったので、このような「数字」をうまく扱っていました。異なるシステムではさらに多くの意味を持っています。1000000000000_の意味は数値であり、それを格納するのは別の話です(これについてはまた後日)。

テキスト(プログラミングではstringと呼ばれています)1000000000000を格納するには、14バイト(各文字に1バイト、基本的には「文字列はここで終わる」という意味の終端NULLバイト)が必要です。これは4つのマシンワードです。3.5バイトで十分ですが、前述の通り、マシンワードでの演算が一番速いです。仮にASCIIがテキストの保存に使われているとすると、メモリ上では次のようになります: (01に対応するASCIIコードをバイナリに変換して、各ワードを別の行に)

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

1ワードに4文字が収まると、残りは次のワードに移動します。残りはすべて(最初の NULL バイトを含む)が収まるまで次のワードに移動されます。オーバーフローしているテキストと同じように動作しますが、右から左へフィットします。複雑に聞こえるかもしれませんが、ここに例を示します。簡単のために、次のように仮定してみましょう:

  • 私たちの想像上のコンピュータは、バイナリの代わりに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

おっと。これは integer overflow と呼ばれるもので、多くの重大な問題の原因となっていて、時には 非常に高価なもの

0 0
9 9
0 1
0 0

そして今、1を追加する:

0099 | +1
0100
00000000 00000000 00000000 00000000 11111111 11111111 11111111 11111111 | +1
00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000000

バイト区切りのスペースと改行を削除すると、より明確になります。この方法での数値の処理は、単一ワードに収まる数値ほど速くはなく、ソフトウェアに実装する必要があります。32ビットCPUに2-32ビットワード数のサポートを追加すると、実質的に64ビットCPUになります (これで64ビット数でもネイティブに動作するようになりましたね?)

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

&001

このような数字を10進数に変換するのは難しいですが。(ただし、16進法ではかなりうまく動作します)(https://math.stackexchange.com/q/597019))

40
40
40
2014-01-07 23:06:37 +0000

あなたのコンピュータがクラッシュすることなく “THIS STATEMENT IS FALSE” を書くこともできます :) スコットさんの答えは特定の計算フレームワークにはぴったりですが、大きな数値を「書く」というあなたの質問は、少なくともそれが解釈されるまでは、それがただのテキストであることを示唆しています。このようなデータは、ある特定の型に制限されていなければならず、その型のコンピュータ定義には、このデータに対してどのような操作がどのように実行できるかが記述されています。数値にテキストを単純に追加することはできませんが、数値にテキストを乗算することができないのと同じように、これらの値のいくつかは型の間で変換することができます。これらの値の型では、すべてのビットが桁に関する情報を格納するために使用されます。また、使用するプラットフォームの言語やアーキテクチャによっては、16ビットの整数や256ビットの整数を持つことができます。直感的には、signed integersがゲームの名前です。慣習として、0から2^32-1までのすべての値を割り当てることになっています - この方法では、-2^(n-1)2^(n-1)-1の2つの書き方を扱う必要があるという混乱を避けることができます。つまり、32ビット符号付き整数は+0から-0までの値を保持することになります。これで、小数点以下の要素を含まない整数を扱いました。これを表現するのはもっと難しいです。整数以外の部分は、感覚的には -21474836482147483647 の間のどこかにしかありませんので、それを表現するために使用されるすべての余分なビットはその精度を高めます。問題は、単純な 10 進数の 0 を分母に 2 の累乗しか持てない分数の和として正確に表現することができないことです! 整数として格納しつつ、代わりに基数(小数)の点を入れることに同意した方がはるかに簡単ではないでしょうか?これは _fixed point 数と呼ばれるもので、ここでは 1 を格納しますが、代わりに 0.1 と読むことに同意します。

計算に使われる比較的一般的な型は 1234100 です。これは、符号値を格納するために1ビットを使用し、その後、指数と記号を格納するためにいくつかのビットを使用しています。このような割り当てを定義する標準がありますが、 32-bit float の場合、格納できる最大数は圧倒的な

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

となります。ブラウザで利用できるJavaScriptは64ビットのフロートを使用していますが、それでもうまくいかないのです。これをアドレスバーにコピーしてエンターキーを押すだけです。ネタバレ注意:結果は007ではありません。

javascript:alert(0.1+0.2);

Microsoft .NET 4.5の 1234.100 のような代替型もありますが,理論的には上下限がなく,「バッチ」で計算しなければなりません.

31
Advertisement
31
31
2014-01-07 21:58:50 +0000

真に、もしコンピュータが1ワード(32ビットシステムでは4バイト)の単純な2進数表現を使って数字を格納することにこだわるならば、32ビットコンピュータは2^32までの数字しか格納できません。しかし、あなたがそれらを使って何を達成したいかに応じて、数字をエンコードする他の方法がたくさんあります。コンピュータはそれらをエンコードするために様々な方法を使うことができます。標準規格 IEEE 754 では、2^32より大きい数をエンコードするためのルールが定義されています。ざっくり言うと、コンピュータは32ビットを数字のいくつかの桁を表す部分と、数字のsizeを表す他のビット(すなわち、指数、10^x)に分割することによって、これを実装することができます。これにより、サイズの面では数値のrangeをより大きくすることができますが、精度の面では妥協してしまいます(これは多くの目的には問題ありません)。もちろん、コンピュータはこのエンコーディングに複数の単語を使うことができ、利用可能なエンコーディングされた数値の大きさの精度を上げることができます。IEEE 標準の単純な 10 進 32 バージョンでは、10 進数で約 7 桁の精度の数字と、大きさで約 10^96 までの数字が可能です。明らかに、エンコーディングではより多くの単語を無制限に使うことができます (ただし、エンコードされたフォーマットに変換したり、エンコードされたフォーマットから出力したりするためのパフォーマンスのペナルティはあります)。これを行う方法の一つとして、数百桁の精度の計算を可能にするエンコーディングスキームを使用したExcel用の素晴らしいオープンソースのアドインがあります。このアドインはXnumbersと呼ばれており、こちらから入手できます。コードはVisual Basicで書かれていますが、可能な限り最速ではありませんが、理解しやすく修正しやすいという利点があります。コンピュータがどのようにして長い数字のエンコーディングを実現するかを学ぶのに最適な方法です。また、プログラミングツールをインストールしなくても、Excel内の結果を使って遊ぶことができます。

24
24
24
2014-01-07 23:47:36 +0000

それはあなたの質問の中にあります。

紙に好きな数字を_書くことができます。白い紙に1兆個のドットを書いてみてください。遅いし、効果がありません。だからこそ、私たちは10桁の数字を使って大きな数字を表現しています。億」や「兆」などのような大きな数字には名前がついているので、「one one one one one one one one one one one...」と声に出して言わないようになっています。しかし、私たち、人間は、一般的に10桁の数字システムを使用しており、コンピュータは、電子的であることから、2桁のシステムバイナリ)を使用しています。数字の32と64はたまたま2の累乗であり、100万と1兆は10の累乗です。例えば、65536のような大量の数字よりも、これらの数字を使って操作する方が簡単なのです。コンピュータは、数字をより多くの桁数に分解します。私たちは好きな数字を書くことができるし、私たちがそう設計すれば、コンピュータもそうすることができるかもしれない。

15
Advertisement
15
15
2014-01-08 00:42:45 +0000

32bitと64bitはメモリのアドレスを指します。コンピュータのメモリは郵便受けのようなもので、それぞれ異なるアドレスを持っています。CPU (Central Processing Unit) はこれらのアドレスを使用して RAM (Random Access Memory) 上のメモリの位置をアドレスします。CPUが16ビットのアドレスしか扱えなかった頃は、32mbのRAMしか使えませんでした(当時は巨大に見えました)。32bitになると4+gbになりました(当時は巨大に見えました)。しかし、プログラムは数字やテキストを保存するためにメモリの複数のブロックを割り当てることができますが、それはプログラム次第であり、各アドレスのサイズとは関係ありません。だから、プログラムはCPUに「10個のアドレスブロックを使用して、非常に大きな数字や10文字の文字列などを保存します」と伝えることができます。 余談: メモリのアドレスは「ポインタ」によって指し示されるので、32と64ビットの値は、メモリにアクセスするために使用されるポインタのサイズを意味します。

13
13
13
2014-01-08 06:44:38 +0000

Ponieważ wyświetlanie liczby odbywa się za pomocą pojedynczych znaków, a nie liczb całkowitych. Każda cyfra w liczbie jest reprezentowana osobnym znakiem dosłownym, którego wartość całkowita jest określona przez stosowane kodowanie, na przykład 'a' jest reprezentowane przez wartość ascii 97, natomiast '1' jest reprezentowane przez 49. Sprawdź tabelę ascii tutaj . Wyświetlanie zarówno ‘a’ jak i ‘1’ jest takie samo. Są to dosłowne znaki, a nie liczby całkowite. Każdy znak dosłowny może mieć maksymalną wartość 255 w 32-bitowej platformie przechowującej wartość w rozmiarze 8 bitów lub 1 bajta (jest to zależne od platformy, jednak 8 bitów jest najczęściej spotykaną wielkością znaków), dzięki czemu mogą być one grupowane i wyświetlane. To, ile oddzielnych znaków mogą one wyświetlać, zależy od posiadanej pamięci RAM. Jeśli masz tylko 1 bajt pamięci RAM, możesz wyświetlić tylko jeden znak, jeśli masz 1GB pamięci RAM, możesz wyświetlić dobrze 1024 *1024 *1024 znaków (Zbyt leniwy, aby zrobić matematykę).

Ograniczenie to dotyczy jednak obliczeń, jednak domyślam się, że jesteś zainteresowany standardem IPV4. Chociaż nie jest on całkowicie związany z komputerem bit-size, w jakiś sposób wpływa na standardy. Podczas tworzenia standardu IPV4, wartości ip były zapisywane w 32-bitowych liczbach całkowitych. Teraz, po podaniu wielkości, stał się on standardem. Od tego zależało wszystko, co wiemy o Internecie, a potem zabrakło nam adresów IP do przypisania. Więc jeśli standard IP został zmieniony na 64-bitowy, wszystko po prostu przestanie działać, w tym Twój router (zakładam, że to jest poprawne) i inne urządzenia sieciowe. Tak więc należy stworzyć nowy standard, który właśnie zamienił 32-bitową liczbę całkowitą na 128-bitową. I dostosował resztę standardu. Producent sprzętu musi tylko zadeklarować, że wspiera ten nowy standard i dostanie on wirusy. Choć nie jest to takie proste, ale chyba masz rację.

Zaprzeczenie: Większość z wymienionych tu punktów jest zgodna z moim założeniem. Być może pominąłem tu ważne punkty, żeby to uprościć. Nie jestem dobry w cyfrach, więc musiałem pominąć kilka cyfr, ale chodzi mi o to, aby odpowiedzieć OP na pytanie, dlaczego nie rozbije komputera.

13
Advertisement
13
13
2014-01-08 11:27:08 +0000

プロセッサーには「言葉」があります。いろいろな言葉があります。人々が「32ビットプロセッサ」と言うとき、彼らはほとんどの場合、「メモリバス幅」を意味します。この言葉は、送信(24ビット)と制御(他のビット)に対応するコンピュータのサブシステムを指す異なる「フィールド」で構成されています。正確な数値は間違っているかもしれませんが、マニュアルで確認してください。SSEやMMXの命令セットは長い整数を格納できる。生産性を落とさない最大の長さは、現在のSSEのバージョンにもよりますが、常に64ビットの倍数程度です。

現在のOpteronプロセッサは、256ビット幅の数値を扱うことができます(整数はよくわかりませんが、floatは確実です)。(1)バス幅が演算幅に直接接続されていない、(2)異なるワード(メモリワード、レジスタワード、バスワードなど)でも互いに接続されていない、それ以外は8か16か24くらいの共通の除数を持っている、ということです。多くのプロセッサは、6ビットのワードを使っていました(しかし、その歴史はあります)。

10
10
10
2014-01-08 20:39:13 +0000

コンピューティングデバイスの目的は、一般的に、データを受け入れ、処理し、保存し、放出することです。基盤となるハードウェアは、これら4つの機能を実行するのに役立つ機械にすぎません。

ソフトウェアは、どのようにデータを受け入れ、どのように処理し、どのように保存し、どのように他の人に提供するかをマシンに伝えるコードです。32 ビットマシンの場合、データを処理するレジスタのほとんどは 32 ビット幅しかありません。これは、マシンが2^32を超える数を扱えないという意味ではありませんが、より大きな数を扱いたい場合、マシンがそれを受け入れ、処理し、保存し、放出するのに1サイクル以上かかるかもしれないことを意味します。ソフトウェアが大きな数字を扱うように設計されている場合、より大きな数字をどのように扱うかを伝える一連の命令をCPUに送ります。例えば、あなたの数字は2つの32ビットレジスタで表されます。1,234個の数字を加算したい場合、ソフトウェアはCPUに、まず1,234個の数字を下位レジスタに加算し、オーバーフロービットをチェックして、下位レジスタには大きすぎる数字が加算されていないかどうかを確認するように指示します。

小学生がキャリーを使って足し算をするように教えられているのと同じように、CPUは1つのレジスタに保持できる数よりも大きな数を扱うように指示することができます。これは実用的なサイズの数のためのほとんどの一般的な数学操作のために真実である。

8
Advertisement
8
8
2014-01-09 15:18:54 +0000

32ビットコンピュータは1つのマシンワードに2^32までの数字しか格納できませんが、それ以上のデータを扱うことができないわけではありません。また、データバスを介して一度に4バイトのデータを送信する際には、データを4つのバイトチャンクに分割しなければなりません。

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

6
6
6
2014-01-10 19:11:43 +0000

他の多くの回答に追記しておきますが、この質問の中で見落とされている重要な事実があります。レジスタサイズとは何の関係もありません。32ビットCPUの多くは64ビットや128ビットのレジスタを持っている可能性が高いです。特にx86の製品ラインを参考にすると、最近の民生用CPUは全て64bitですが、特殊な目的で256bitまでのレジスタを持っています。

このレジスタ幅とアドレス幅の違いは、4bitレジスタと8bitアドレスがあった昔から存在していました。

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

レジスタのサイズがどうであろうと、大きな数値でも計算できるのは、大きすぎる計算は、レジスタに収まるように、いくつかの小さな計算に分解できるからです。

6
Advertisement
6
6
2014-01-10 21:36:01 +0000

すでに与えられている回答は、実際にはかなり良いものですが、異なる側面から問題を取り上げているために、不完全なイメージを提示する傾向があります。

You’re mixed up several concept in your question , and one of them (“32 bit”) can actually refer to the variety different things (and different answers has assumed different interpretations). これらの概念はすべて、様々なコンピューティングコンテキストで使用される(または利用可能な)ビット数(1と0の)と関係する何かを持っています(私がこれによって何を意味するかはうまくいけば以下の例によって明らかにされるでしょう)が、概念はotherwise unrelatedです。IPv4とIPv6の間の主要な(または少なくとも最もよく知られている)区別は、アドレス空間(すなわち、ネットワーク上の異なる場所を区別するために使用することができるアドレスのセット)がIPv6で大きくなっているということです。これは、ネットワークを介して送信されるデータの各パケット内のビット数が、パケットの送信者と受信者を識別するためにallocated(すなわち、目的のために脇に置いておく)されているかに関係しています。また、アドレス空間は、封筒に宛名と返信用のアドレスを書くときに「許される」文字数のようなものです。 - これまでの他の回答では、このことについて言及されているのを見たことがありません。 - コンピュータメモリの「ワード」(32ビットと64ビット)は、一般的にコンピュータが使用する、あるいは「考える」最小のデータと考えることができます。また、このような場合には、「コンピュータには、そのようなデータは存在しない」ということになりますが、「コンピュータには、そのようなデータは存在しない」ということになります。 - Guffaさんの回答 sanarisさんの回答 gronostajさんの回答 の最初の段落を参照してください。 - 32ビットの_ポインタは、単語であるかもしれないし、そうでないかもしれませんが、それにもかかわらず、原子的に扱われます(つまり、より小さな構成要素に分解できない個々の単位として)。ポインタは、コンピュータが任意のデータの塊のメモリ内の位置を記録するための最低レベルの方法です。コンピュータが使用する(実際にはオペレーティングシステムが使用する)ポインタのサイズによって、1つのポインタでアクセスできるメモリの範囲が制限されていることに注意してください。これは、IPv4が可能なインターネットアドレスの範囲を制限する方法に似ていますが、例えば特定のウェブページに存在することができるデータの量を制限することはありません。しかし、ポインタのサイズは、ポインタが指すことができるデータ自体のサイズを制限するものではありません。(データサイズがポインタの範囲を超えることを許可するスキームの例については、Linuxの inodeポインタ構造 をチェックしてください。ポインタは通常、ハードドライブ領域ではなくランダムアクセスメモリへのポインタを指しているので、これは一般的な「ポインタ」という言葉の使い方とは少し異なることに注意してください。おそらく、図書館資料の索引付けのためのデューイ十進法は少し似ているのではないでしょうか? - SiteNookさんの回答を参照してください。 - 上記のポインタの私の説明は、いくつかの微妙な詳細を省略しており、おそらく完全に正しいわけではないことに注意してください。しかし、プログラマーが直接ポインタを使って作業するプログラミング言語では、私が描いた精神的なモードは、実用的な目的のために通常は十分です。 - コンピュータが「表示することができる」数字は、コンピュータのハードウェアやオペレーティングシステムによって制限されていません(実用的な目的のために)。 - 非コンピューティングのアナロジー: 紙に書くこと - user1306322さんの回答 Bigbio2002さんの回答

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

5
5
5
2014-01-11 23:24:10 +0000

あなたの頭の中では10桁の数字しか知らない。0から9まで あなたの脳内では確かにコンピュータとは違った方法でエンコードされています

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

大きな数を理解しなければならないときには、必ずシステムを使います。一番左の数字が最も重要です。

40億の異なる値を区別することができるコンピュータは、同じように、ある値の集合の中で、一番左の値を次の値の40億倍の重要な値にしなければなりません。実際には、コンピュータは全く気にしません。数字に「重要度」を割り当てることはしない。プログラマはそれを処理するために特別なコードを作らなければなりません。

ある値が人間の頭の中のユニークな記号の数、9よりも大きくなるたびに、左の数字に1つ足していきます。コンピュータがこれに対処するシステムを持っていない限り、それは単に余分な数があったことを忘れて、0を書くでしょう。幸いにも、コンピュータはこの場合に発生する「オーバーフローフラグ」を持っています。

3+3=6

あなたは学校でメソッドを学んだかもしれません。アルゴリズムです。アルゴリズムはいたってシンプルです。一番左端の2つの記号の足し算から始めます。

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

次に次のスロットに移動して同じ足し算を行います。

987+321 is more difficult.

オーバーフローが発生していたので、次の数字に1を足すということです。

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

これ以上の数字はないので、スロットを作ってオーバーフローフラグが上がっていたので1を挿入するだけです。

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

コンピュータは、人間のように10個だけではなく、2^32個か、もっと良い2^64個の異なる記号を持つ以外は、全く同じ方法でこれを行います。幸いなことに、プログラマーにとってはそれは抽象化されています。ビットは2桁でしかない、なぜならそれは電力線で表現するのが簡単だからだ。ライトが点灯しているか消灯しているかのどちらかです。

最後に、コンピュータはどんな数字でも単純な文字列として表示することができました。それがコンピュータの得意とするところです。文字列と内部表現を変換するアルゴリズムは非常に複雑です。

5
Advertisement
5
5
2014-01-11 17:59:58 +0000

典型的なLinuxシステム上の多くのプログラムが大きな数の処理と出力をどのように処理しているか、実際の例を見てみましょう:

libgmp - The GNU Multiple Precision Arithmetic Library は、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
5
5
2014-01-09 16:36:20 +0000

例えば電卓で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++よりもはるかに大きな(および/またはより正確/正確な)数値を扱うことができることが想像できます。

3
Advertisement
3
3
2014-01-12 00:41:20 +0000

なぜなら、あなたが表示しているのは数字ではなく、(コンピュータが関係している限りでは) 文字列、つまり数字の羅列だからです。確かに、数字を扱うアプリ(電卓のようなものだと思いますが)では、このような数字を扱えるものもあると思います。どんなトリックを使っているのかは知らないけど…。他のもっと凝った回答でカバーしているものもあると思いますが

0
0
0
2016-12-30 11:54:31 +0000

この回答の内容のほとんどは、元々は この回答 (他の質問が重複しているとマークされる前に書かれたもの)から来ています。8ビット値の方が概念的に理解しやすく、32ビット演算のような大きな値にも同じ概念が適用されるからです。

8ビットの2つの数字を足し算すると、得られる最大の数字は(0xFF + 0xFF = 1FE)です。実際には、8 ビットの 2 つの数字を掛け合わせても、(0xFF * 0xFF = 0xFE01)得られる最大の数字は、8 ビットの 2 倍の 16 ビットのままです。例えば、8ビットプロセッサは8ビットしか記録できません)これは正確ではありません。8ビットプロセッサは、8ビットのチャンクでデータを受け取ります(これらの「チャンク」には、一般的に「ワード」という正式な用語があります)。8ビットプロセッサでは、8ビットのワードが使用されます。64 ビット・プロセッサでは、64 ビット・ワードを使用できます)

つまり、コンピュータに 3 バイトのバイトを与えると、次のようになります。CPUは次のような結果を生成することができます: 0100 0000 0100 0010 xxxx xxxx xxxx xxxx xxxx 1101 0111 a.k.a.: 0x4082xxxxD7 さて、それを解釈してみましょう: 0xは単に次の桁が16進数であることを意味しています。
0xは、次の桁が16進数であることを意味しています。これらのビットを 0 や 1 で埋めないのは、「ADD」命令(CPU に送られた命令)によって、これらのビットが変更されない可能性があるからです(この例で使用している他のほとんどのビットは、フラグビットを除いて変更される可能性があります)。

0xA5×0xCBの数学的な結果は0x82D7となります。まあ、もう一度言いますが、これは私が使用しているサンプルシナリオであり、実際のアセンブリ言語(Intel 8080や8088や多くの新しいCPUで使用されているIntel x86 16ビット)に近い概念を意図しています。例えば、"C “レジスタは一般的にカウント操作のインデックスとして使用され(ループの典型的なもの)、"B "レジスタはメモリの位置を指定するのに役立つオフセットの追跡に使用されるなど、いくつかの共通のルールがあるかもしれません。したがって、"A "と "D "は、一般的な算術関数のいくつかでは、より一般的に使用されているかもしれません。その文書には、各命令がどのレジスタを使用するかが明記されているはずです。(したがって、どのレジスタを使用するかについての選択は、多くの場合、CPUの設計者によって指定され、アセンブリ言語のプログラマではありません。しかし、多少の柔軟性はあります)

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

例えば、複数のADD命令があるかもしれません。あるADD命令は16ビットの結果をAレジスタとDレジスタに格納し、別の命令は8つの下位ビットをAレジスタに格納し、Dレジスタを無視し、オーバーフロー・ビットを指定するかもしれません。その後、後で(Aレジスタの結果をメインRAMに格納した後に)、8ビットの上位ビットだけをレジスタ(おそらくAレジスタ)に格納する別のADD命令を使用することができます。

(希望する結果に収まるようにあまりにも多くのことを減算した場合に備えて、一般的に「アンダーフロー」フラグもあります。)

物事がどれだけ複雑になったかを示すために: Intel 4004 は 4 ビットの CPU でした。それは A、B、C、および D.という名前の 8 ビットのレジスタを持っていた Intel 8086 は 16 ビット CPU だった。それは示される 16 ビットのレジスタを持っていました インテル 80386 は 32 ビット CPU で、EAX、EBX、ECX、EDX という 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を65,536の倍数ではない値で変更した場合はAXにも影響します)

フラグとレジスタはここで挙げたものだけではありません。

さて、8ビットCPUの場合、メモリへの書き込みの際、4ビットや16ビットではなく8ビットのアドレスを参照することができないという制限があります。詳細はCPUによって異なりますが、そのような制限がある場合は、CPUが8ビットのワードを扱っている可能性があるので、「8ビットCPU」と呼ばれることが多いです。

Advertisement