参考: 日経ソフトウエア 2020年1月号 [雑誌], pp.144-145
4バイトで表現される。今回実行した環境ではリトルエンディアンで格納されていた(下位バイトが若いアドレスに格納される)。
その4バイトの最上位ビットが符号(0: 正, 1: 負)、
続く8ビットが指数部(実際の指数に127を足した値)、
残りの23ビットが假数部(全24ビットのうち暗黙の最上位ビット1を外した値)。
#include <iostream> #include <math.h> using namespace std; int main(void) { float a = -123.456; printf("a = %.20f\n", a); printf("floatは何バイトか: %lu\n", sizeof(float)); // その4バイトを1個の32ビット整数に刻み直す: // &aで変数aのポインタを取得し、 // (uint32_t*)でそのポインタをuint32_t型のポインタにキャストし、 // *でそのポイント先に存在しているデータを取得する。 uint32_t internal_representation = *(uint32_t*)&a; printf("内部表現は: 0x%X\n", internal_representation); // その4バイトを若いアドレスから1バイトずつ見てゆく: // &aで変数aのポインタを取得し、 // (uint8_t*)でそのポインタをuint8_t型のポインタにキャストし、 // 8ビット刻みで順番に参照する。 printf("若いアドレスから1バイトずつ見てゆくと: "); for (int i = 0; i < 4; i++) { printf("0x%X, ", ((uint8_t*)&a)[i]); } putchar('\n'); // 符号、指数部、假数部を個別に取り出す。 uint8_t sign = (internal_representation >> 31) & 1; uint8_t exp_part = (internal_representation >> 23) & 0xFF; uint32_t mantissa = internal_representation & 0x7FFFFF; printf("符号: 0x%X\n", sign); printf("指数部: 0x%X\n", exp_part); printf("假数部: 0x%X\n", mantissa); // 元の数に戻してみる。 mantissa += (1 << 23); exp_part -= 127; float sum = 0; for (int i = 0; i < 24; i++) { sum += ((mantissa >> (23 - i)) & 1) * pow(2, -i); } printf("元の数字に戻すと: "); printf("%.20f\n", pow((-1), sign) * sum * pow(2, exp_part)); return 0; }