floatタイプのメモリへのストレージ

4053 ワード

まず、テーマを見てみましょう.
#include "stdafx.h"
#include 
#include 
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	float a = 1.0f;
	cout << (int)a << endl;                                    //   1
	cout<< &a <

上記のテスト結果について、&aと(int)aの出力結果はよく理解できますが、(int&)aの結果はよく分からないようです.
106553216の値は、実際に1.0 f浮動小数点数タイプの再メモリで表されるバイナリ数が10進数で表される値に直接変換されます.
a=1.0 fメモリでの表示(バイナリ):0011111,10000000,000,000,000,000,000,000,000,000,000(浮動小数点数のバイナリの表示は以下を参照)のうち、最上位1は符号で、残りの桁数の10進数は106553216です.
つまり、(int&)aはaの参照を強制的に整数型に変換することであり、aが存在するメモリを意味し、本来定義されたときはfloat型であり、初期は1.0 fであったが、今はint型でこのメモリを説明する(つまりaが存在するメモリアドレスのデータはもともとfloat型で記憶されているので、int型で説明しなければならない).
一方、(int)aは、浮動小数点数型aを強制型からint型に変換する結果を出力ので、結果は1となる.
次に、2進数での浮動小数点数の表示方法(C/C++浮動小数点数のメモリへの格納方法)について説明します.
いずれのデータもメモリには、例えばshort型データ1156のようなバイナリ形式で格納され、そのバイナリ表現形式は10000000、10000000、100である.Intel CPUアーキテクチャのシステムでは、Intel CPUのアーキテクチャが小端モードであるため、10000000(低アドレスユニット)10000000 100(高アドレスユニット)が格納される.しかし、メモリに浮動小数点数をどのように格納しますか?現在、すべてのC/C++コンパイラはIEEEが制定した標準浮動小数点フォーマット、すなわちバイナリ科学表現法を採用している.
バイナリ科学表現法では,S=M*2^Nは主に3つの部分から構成される:シンボルビット+次数符号(N)+末尾数(M).float型データの場合、そのバイナリは32ビットあり、シンボルビット1ビット、階層コード8ビット、末数23ビットである.double型データの場合、バイナリは64ビット、シンボルビット1ビット、階層コード11ビット、末尾52ビットである.
                31        30-23       22-0
floatシンボルビット符号末尾数
                63        62-52       51-0
doubleシンボルビット番号末尾数
符号ビット:0は正、1は負
ステップコード:ここで、ステップコードはシフトコードで表され、float型データについては所定のバイアス量が127であり、ステップコードには正の負があり、8ビットバイナリについては−128−127、double型については−1024−1023、表示範囲は−1024−1023である.例えばfloat型データについては、ステップコードの真の値が2であると127を加える129となり、そのステップコード表現形式は10000010となる.
端数:有効デジタルビット、すなわち部分バイナリビット(小数点以下のバイナリビット)は、Mの整数部分が一定であることを規定するので、この1は記憶されない.
次に例を示します.
float型データ125.5を標準浮動小数点フォーマットに変換
125バイナリ表示形式は1111101、小数部はバイナリ1、125.5バイナリは1111101.1、所定の端数の整数部は一定であるため1.1111011*2^6、次数コードは6、127を加えて133となると100000101、端数については整数部1を削除して1111011となり、その後に0を補って23桁にする、11110110000000億ドル
そのバイナリ表現形式は
0 100000101,11110110000000,000,000,000は、メモリに格納されます.
00000000低アドレス
00000000
11111011
01000010高アドレス
逆にバイナリ形式で浮動小数点数を求めるとすると0,100000101,11110110000000,000,000,000,000,000.
符号が0であるため、正数となります.次数は133-127=6、端数は11110110000000、端数は1.1111011である.だからその大きさは
1.1111011*2^6は、小数点を6桁右にシフトして1111101.1を得るが、1111101の十進法は125、0.1の十進法は1*2^(-1)=0.5であるため、その大きさは125.5である.
同様にfloat型データ0.5をバイナリ形式に変換すると
0.5のバイナリ形式は0.1で、正の数の部分を1にしなければならないため、小数点を1桁右にシフトすると1.0*2^(-1)となり、その次数は-1+127=126で01111110となり、端数1.0は整数の部分を除いて0となり、0から23桁の0000000000000000億円を足した場合、そのバイナリ形式は
0 01111110 00000000000000000000000
以上の解析からfloat型データの最大表現範囲は1.11111111111111111*2^127=3.4*10^38であることがわかる
double型データの場合は同様であるが,その階層コードは11ビット,バイアス量は1023,端数は52ビットである.
これにより、float a=1.0 fのバイナリ格納値が得られにくくなり、ステップ値が0、オフセット127となり、得られたバイナリビットが011111111、最上位がシンボルビット0となり、後のビット数が0であるため、直接0を補い、23ビットをそろえる.
結果:0,011,111,111,000,000,000,000,000,000,000,000,000,000,000,000,000.
//    
#include 
using namespace std;

int main(int argc, char *argv[])
{
    float a=125.5;
    char *p=(char *)&a;
    printf("%d
",*p); // 0 printf("%d
",*(p+1)); // 0 printf("%d
",*(p+2)); // -5 printf("%d
",*(p+3)); // 66 return 0; }

125.5メモリでの表現:125.5変換バイナリ:1111101.1、整数ビット1、ビット1.1111011*2^6、ステップコード6、オフセット127 133、バイナリ100000101.さらに末尾数を計算し、整数部分の1を1111011に取り除き、残りは後に0を補い、23ビットを補います.したがって、バイナリは、0 100000101 11110110000000と表示されます.
float型125.5のメモリへの格納方法は、以下の通りである.
00000000低アドレス
00000000
11111011
01000010高アドレス
従って、pおよびp+1が指すユニットについて、格納されたバイナリ数が表す10進数整数は0である.
一方、p+2が指すセルについては、char型のポインタであり、符号付きのデータ型であるため、11111011、符号ビットが1である負数となり、メモリにバイナリが補符号で記憶するため、その真値は-5となる.
p+3が指すセルの場合、01000010は正数であり、その大きさは66である.上記のプログラムの出力結果はその正確性を検証した.