前回の記事に引き続き、char型と浮動小数点型のデータの格納について検討していきます。
1.Char型データの格納方法
コードを使用して、全員にデモンストレーションするだけです。
#include<stdio.h>
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a));
return 0;
}
このコードを読むと、i の値が a[i] に支払われ、a[i] の値は -1、-2、-3、...、-999、-1000、サイクルが進むにつれて、しかし本当に -1000 が出力されるのでしょうか?
確かにそうではありません
char 型ではそのような小さな数値を格納できないという問題が発生するため、次に char 型のデータを詳しく調べます。
int 型のデータは 4 バイトを占有するのに対し、char 型のデータは 1 バイトしか占有しないことは誰もが知っています。したがって、ビットで言えば、int 型は 32 ビットを占有するのに対し、char 型は 8 ビットしか占有しません。
1 ビットのサイズはバイナリに適合します
したがって、それらの最大値は次のようになります (ここでは符号なしとみなされます)。
int 1111 1111 1111 1111 1111 1111 1111 1111(4,294,967,168)
char 1111 1111 (255) と同じ
ただし、最初のビットは符号ビットであり、0 は正の数を表し、1 は負の数を表すことを考慮する必要があります。
したがって、char 型の最大の数値は 2 進数で 0111 1111 と表現され、10 進数では 127 になります。
char型の最小の数値は2進数で 1000 0000(-128)となりますが、これは固定値であり、char型でこの数値が現れた場合はそのまま-128とみなします。
そして、char のバイナリ値は、動作中に -128 と 127 の間を循環します。つまり、バイナリ値 127 +1 が -128 になるとき、同様に、-1 から -1 に始まり、- に減ります。 128、そして減らすと 1 は 127 になり、ゼロになるまで循環します。
したがって、-1000 のような数値を保存するだけではもちろん十分ではありません。
strlen 関数をもう一度見てみましょう。strlen 関数は文字列の長さを測定し、\0 に達するまで終了しないことは誰もが知っています。
したがって、最終的な出力値は 127+128 になります。
コードを実行してみましょう
えっ!歩く!
このループを円に変えることもできます
これはとてもわかりやすいですね
2. 浮動小数点数がどのように保存および処理されるかを理解する
まず一般的な浮動小数点数を見てみましょう。
3.1415926 (小数点付きの 1 つだけ)
1E10 (科学的表記法で、1.0×10^10 を表す)
浮動小数点数の型には、float、double、long double 型が含まれます。
引き続き、浮動小数点数に関する次のコード セットを観察してください。
#include<stdio.h>
int main()
{
int n = 9;
float* pfloat = (float*)&n;
printf("n的值为:%d\n", n);
printf("*pfloat*的值为:%f\n", *pfloat);
*pfloat = 9.0;
printf("num的值为:%d\n", n);
printf("*pfloat的值为:%f\n", *pfloat);
return 0;
}
以下が出力結果ですが、思った通りでしょうか?
まず、上記の 2 つの印刷データを見てみましょう。
n の値は 9 で、これは整数型データです。次に、整数型データ、つまり %d 出力を出力すると、出力は 9 であることがわかります。
しかし、float 型のポインタを定義すると、このポインタは n のアドレスを指し、最後にこのポインタをデコードして出力すると、それは 0.000000 であり、整数出力は同じ値ではないことがわかります。
つまり、整形データ9を格納しておき、整形して取り出しても、データは変化しない。
しかし、整数データを保存し、それを浮動小数点データで取り出すと、状況は異なります。
したがって、これを使用して、整数の記憶規則が浮動小数点型の記憶規則と異なることを証明します。
以下の同じ出力データは逆になります。
浮動小数点データを使用して格納し、整数データを使用して取り出すと、次のような文字列が出力されます。
ただし、浮動小数点データで格納されているデータは、浮動小数点データとして取り出すと正常に使用できることから、整数データと浮動小数点データの格納規則が異なることがわかります。
それで、違いは何ですか?
国際標準 IEEE (電気電子工学研究所) 754 によると、任意の 2 進浮動小数点数 V は次の形式で表現できます:
(-1)^S * M * 2^E
(-1)^s は符号ビットを表し、s=0 のとき V は正の数、s=1 のとき V は負の数になります。
M は、1 以上 2 未満の有効な数値を表します。(2進数に変換すると0/1のみなので1≦M<2)
2^E は指数ビットを表します。
その意味は
V は 2 進浮動小数点数、V=(-1)^S * M * 2^E です。(-1)^S で S=0、(-1)^S=1 の場合、この V は次のようになります。正の数を表します。S=1 の場合、(-1)^S=-1 の場合、V は負の数を表します。
例を挙げてみましょう
5.5
一桁の 5 は 2 進数に変換され、101 と表現されます。
小数点以下の値の重みは負の数になります。
図に示すように重みを理解するのが簡単になります。
すると、5.5を2進数で表すと101.1となり、小数点を移動して科学表記に直すと1.011となり、上記のVの表現形式より、 5.5=(-1)^0* 1.011 *2 と書くことができます。 ^2、( -1)^0 は正の数であることを意味し、2^2 は小数点を 2 桁後方に移動することを意味します。これは、V=(-1)^S * M * 2^E であるため、S=0 となります。 M=1.011、E =2 であるため、コンピュータがデータを格納する場合、浮動小数点数を格納する効果を得るには、S、M、および E をコンピュータに格納するだけで済みます。
私たちも知っておく必要があるのは、
float 型は 32 ビット浮動小数点型です
double 型は 64 ビット浮動小数点型です
前述したように、1≤M<2、つまり M は 1.xxxxxx の形式で記述できます。xxxxxx は小数部を表します。
IEEE 754 では、M をコンピュータ内に保存する場合、デフォルトではこの数値の最初の 1 桁が常に 1 であるため、これを破棄して後ろの xxxxxx の部分だけを保存することが規定されています。小数点の前 1. その値を復元できます。これを行う理由は、小数点をより正確にするためにビットを節約するためです。double は float よりも小数点以下の桁数が多く格納されるため精度が高いため、double は倍精度浮動小数点型、float は単精度浮動小数点型とも呼ばれます(double が 2 倍であるというわけではありません)。 float の精度ですが、より多くのマルチビットを格納できます)
しかし、すべての浮動小数点データを正確に保存できるでしょうか?
①Mの保管
たとえば、5.3 という数字を与えます。
類推すると、後で M を何桁足しなければならないとしても、小数点以下の 3 の真の値を正確に表現することは決してできないことがわかります。
弊社コンパイラの監視機能により発見
私たちの f は確かに 3 よりも少し悪いです
したがって、一部の浮動小数点数はコンピュータに正確に格納できず、わずかな誤差が依然として残ります。
②Eの保管
インデックス E に関しては、状況はさらに複雑です。
まず、E は unsigned int です。
これは、E が 8 ビットの場合、その値の範囲は 0 ~ 255 であり、E が 11 ビットの場合、その値の範囲は 0 ~ 2047 であることを意味します。ただし、科学表記法の E は
負の数になる可能性があることがわかっているため、IEEE 754 では、メモリに格納するときに E の実数値に中間数を加算する必要があると規定しています。8 ビット E の場合、この中間数は 127 です。 11 桁の E の場合、この中間番号は 1023 です。たとえば、2^10 の E は 10 であるため、32 ビット浮動小数点数として保存する場合は、10+127=137、つまり 10001001 として保存する必要があります。
コードを使用してデモしてみましょう
int main()
{
float f = 5.5;
//101.1
//科学计数法:(-1)^0 * 1.011 * 2^2
//二进制存储:0 10000001 011 00000000000000000000
//十六进制表示:40b00000
return 0;
}
2 進数で見ると、最初の 0 はその数値が正の数であることを意味します。
前述の通り、2^2、Eは2なので、Eを格納する際に中間値を加算する必要があります 浮動小数点数は8桁のEなので、127を足して2進数に変換すると、2+127は2進数に変換すると10000001となります最後のはMです。前述の通り、小数点以下は切り捨てられ、小数点以下の数字だけが残るので、Mには011が格納され、以降の数字は で埋められます。 0;
以上がデータの保管方法でしたので、ご参考になれば幸いです。