2018年03月27日
《その350》double型の内部表現(2)
double型の内部表現
double型の内部表現を記述する際の考え方を使って、前回《349》、プログラムを使わずに、実際の数値の内部表現を求めました。
下記のプログラムは、前回のときの考え方をそのまま使って作成したもので、あまりキレイなコードではありませんが、一応の確認には使えるため、今回はこれを利用して、いくつかの数値の内部表現を見てみました。
前回と同じ値 0.6, −12.75 も試してみました。
また、2.0, 0.0625 なども試しましたが、これらの数値には 1 のビットが一つしかないので出力結果が 0 だらけになってしまって、一瞬、焦ります。落ち着いて考えれば納得できますが・・・。
最後の numeric_limits<double> は、付け足しです。
#include <string>
#include <limits>
#include <iostream>
using namespace std;
string to_str(double x);
void print(string x) {
int n = 0;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++)
cout << x[n++];
cout << ' ';
}
cout << '\n';
}
int main() {
cout << "◆double型数値の内部表現\n";
double d;
d = 0.6; cout << "◇" << d << '\n';
print(to_str(0.6));
d = -12.75; cout << "◇" << d << '\n';
print(to_str(-12.75));
d = 2.0; cout << "◇" << d << '\n';
print(to_str(2.0));
d = 0.0625; cout << "◇" << d << '\n';
print(to_str(0.0625));
d = -0.00012; cout << "◇" << d << '\n';
print(to_str(-0.00012));
cout << "\n\nnumeric_limits<double>\n";
cout << "最小値 : "
<< numeric_limits<double>::min()
<< '\n';
cout << "最大値 : "
<< numeric_limits<double>::max()
<< '\n';
cout << "桁数(2進) : "
<< numeric_limits<double>::digits
<< '\n';
cout << "桁数(10進) : "
<< numeric_limits<double>::digits10
<< '\n';
cout << "指数下限 : "
<< numeric_limits<double>::min_exponent
<< '\n';
cout << "指数下限(10進) : "
<< numeric_limits<double>::min_exponent10
<< '\n';
cout << "指数上限 : "
<< numeric_limits<double>::max_exponent
<< '\n';
cout << "指数上限(10進) : "
<< numeric_limits<double>::max_exponent10
<< '\n';
cout << "基数 : "
<< numeric_limits<double>::radix
<< '\n';
cout << "機械ε : "
<< numeric_limits<double>::epsilon()
<< '\n';
cout << "機械ε(\"1より大きい表現可能な最小数\""
"と\"1\"との差)\n";
}
string to_bits(int x) {
string str = "";
while (x) {
if (x % 2) str = '1' + str;
else str = '0' + str;
x /= 2;
}
return str;
}
string to_str(double x) {
// 左端の符号ビット
string sign = (x > 0) ? "0" : "1";
double tmp = (x > 0) ? x : -x;
int a = (int)tmp; // 整数部分(10進数)
double b = tmp - a; // 小数部分(10進数)
// 整数部分の2進数表現文字列
string str1 = to_bits(a);
int exp = 0; // 指数
if (str1 != "") {
exp = str1.size() - 1;
str1.erase(0, 1); // 先頭の 1 を削除
}
string str2 = ""; // 小数部分
int limit = 53 - exp; // 最大で 53桁必要
int f = 0; // フラグ
while (b) {
if (b * 2 >= 1) {
str2 = str2 + '1';
b = b - 0.5;
// 最初の 1 が出現したら f = 1
f = 1;
}
else str2 = str2 + '0';
b *= 2;
// str2 は最初の 1 の桁以下 limit桁の長さ
if (f) --limit;
if (!limit) break;
}
int exp2;
if (str2 != "") {
exp2 = str2.find('1');
// 整数部分がなければ
if (str1 == "") {
// str2 の先頭の 1 を削除
str2.erase(0, exp2 + 1);
// 指数の算出
exp = -exp2 - 1;
}
}
// 指数を変換
exp = exp + 1023;
// 指数部分の2進数表現文字列
string str3 = to_bits(exp);
// 指数部は 11桁
str3 = string(11 - str3.size(), '0') + str3;
// 仮数部は 52桁
str1 += str2;
str1 = str1 + string(52 - str1.size(), '0');
// 全体で 64桁
return sign + str3 + str1;
}
この記事へのコメント
コメントを書く
この記事へのトラックバックURL
https://fanblogs.jp/tb/7482699
※ブログオーナーが承認したトラックバックのみ表示されます。
この記事へのトラックバック