| アーキテクチャ | 合計ビット幅 | 小数部のビット長 | 10進法での仮数部の精度 | 指数部のビット長 | 表現可能な値の範囲 |
| IEEE754 double | 64 | 53 | 16.0桁 | 11 | 10^{-308} ... 10^{308} |
| IA32 | 80 | 64 | 19.3桁 | 15 | 10^{-4932} ... 10^{4932} |
| SPARC | 128 | 113 | 34.0桁 | 15 | 10^{-4932} ... 10^{4932} |
| POWER | 128 | >= 106 | 31.9桁以上 | 11 | 10^{-308} ... 10^{308} |
| IEEE754-2008 binary128 | 128 | 113 | 34.0 | 15 | 10^{-4932} ... 10^{4932} |
long double は(厳密には) 4 倍長のことではない。 SPARC, POWER では 4 倍長に相当する。
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
long double c;
c = 1.0;
cout << sizeof(c) << endl;
cout << c << endl;
cout << setprecision(40) << atan(c) << endl;
return 0;
}
atan(1) = 0.7853981633974483096156608458198757210493メモリでは、
暗黙の1を明示した仮数部のビット表現は、
1.1001 0010 0001 1111 1011 0101 0100 0100 0100 0010 1101 0001 1000 0100 0110 1001 1000 1001これを先頭から 4 ビットずつ区切ると
1100 1001 0000 1111 1101 1010 1010 0010 0010 0001 0110 1000 1100 0010 0011 0100 1100 0100 1...となり、16進法に直すと
c90fdaa22168c234c4.IA32 の 80ビット拡張精度数は暗黙の1もメモリ中に保存されることに注意。
結果
| CPU | OS | compiler | sizeof | atan(1) の出力結果 | ビット |
| SPARC | Solaris | Sun WorkshopPro 9 | 16 | 0.7853981633974483096156608458198756993698 | 3f:fe:92:1f:b5:44:42:d1:84:69:89:8c:c5:17:01:b8 |
| GCC 3.4.3 | 16 | 0.7853981633974482789994908671360462903976 | 3f:fe:92:1f:b5:44:42:d1:80:00:00:00:00:00:00:00 | ||
| Opteron | Solaris | Sun WorkshopPro9 | 12 | 0.7853981633974483096282022398515465511082 | 35:c2:68:21:a2:da:0f:c9:fe:3f:d9:fe |
| GCC 3.4.3 | 12 | 0.7853981633974483096282022398515465511082 | 35:c2:68:21:a2:da:0f:c9:fe:3f:06:08 | ||
| Xeon | Linux | GCC 3.4.0 | 12 | 0.78539816339744830963 | 35:c2:68:21:a2:da:0f:c9:fe:3f:ff:bf |
| FreeBSD | GCC 3.4.2 | 12 | 0.7853981633974483096282022398515465511082 | 35:c2:68:21:a2:da:0f:c9:fe:3f:04:08 | |
| Athlon64 | Linux | GCC 3.4.2 | 16 | 0.7853981633974483096282022398515465511082 | 35:c2:68:21:a2:da:0f:c9:fe:3f:40:00:00:00:00:00 |
| Itanium2 | Linux | GCC 2.96 | 16 | 0.7853981633974482789994908671360462903976 | 00:c0:68:21:a2:da:0f:c9:fe:3f:00:00:00:00:00:00 |
| GCC 3.3 | 16 | 0.78539816339744830963 | 35:c2:68:21:a2:da:0f:c9:fe:3f:00:00:00:00:00:00 | ||
| POWER5 | AIX | XLC V7.0 (with -qlongdouble) | 16 | 0.785398163397448280000 | 3f:e9:21:fb:54:44:2d:18:3f:df:ff:ff:e1:eb:5f:cf |
| GCC 3.4.3 | 8 | 0.78539816339744828 | 3f:e9:21:fb:54:44:2d:18 |
サンプル
宣言 long double f; 定数リテラルの代入 f = 0.1L; f = 1e-1L; 組み込み関数 atanl(f), sinl(f), etc. 出力 cout << setprecision(32) << f << endl; printf("%.32Lf\n", f);
#ifdef __sun
#include <sunmath.h>
#endif
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
long double f;
f = 0.1L;
printf("%.40Lf\n", f);
long double f2;
f2 = atanl(1);
printf("%.40Lf\n", f2);
return 0;
}
結果
| CPU | OS | compiler | atan(1) の出力結果 | 0.1 の出力 |
| SPARC | Solairs | Sun WorkshopPro | 0.1000000000000000000000000000000000048148 | |
| POWER | AIX | XLC 7 | 0.0999999999999999999999999999999996918512 |
注意事項: atanl など、long double 対応の関数を使うには sunmath.h ヘッダをとりこむ。
% /opt/SUNWspro/bin/CC prog.cpp -lsunmath
SPARC アーキテクチャでの拡張倍精度の内部表現
アドレス小
↑0 符号(1 bit):指数MSB(7 bits) 1 指数LSB 2 仮数MSB ・・・ 仮数 ・・・ 15 仮数LSB ↓
アドレス大
- 指数 : 15 bits, BIAS: 0x3fff
- 仮数 : 1 + 112 bits
など。どちらも同じ。
% xlc++ -qlongdouble prog.cpp % xlc++128 prog.cpp
POWER アーキテクチャでの拡張倍精度の内部表現
アドレス小
↑00 符号1(1 bit):指数1 MSB(7 bits) 01 指数1 LSB(4 bits):仮数1 MSB(4bits) 02 仮数1 MSB ・・・ 07 仮数1 LSB 08 符号(1bit):指数2 MSB(7bits) 09 指数2 LSB(4bits):仮数2 MSB(4 bits) 10 仮数2 MSB ・・・ 15 仮数2 LSB ↓
アドレス大
IBM の4倍精度数は、2つの倍精度数の和として表現される。 所謂 exact sum というやつ。
- 指数1 : 11 bits, BIAS: 0x3ff
- 指数2 : 11 bits, BIAS: 0x3ff
- 仮数1 : 1 + 52 bits
- 仮数2 : 1 + 52 bits
「IBM の 4倍精度は、ハードウエアで処理するので速い」と言われる。 但し「4 倍精度数を直接扱い得る回路」を内蔵しているわけではなく、 4倍精度数を 2 つの倍精度数に分割して表現し、そのそれぞれに対して 倍精度用の回路で処理していることを表現している。
g++ -m128bit-long-double src.cppとする。
単精度 1.0E0 倍精度 1.0D0 四倍精度 1.0Q0
整数型
リテラル定数に続けて、アンダースコアと「種別番号(INT_KIND)」を付する。
例:「1」の表現
サイズ 範囲 プログラム中での表現 8ビット整数 -2^7 から 2^7-1 1_1 16ビット整数 -2^15 から 2^15-1 1_2 32ビット整数 -2^31 から 2^31-1 1_3 64ビット整数 -2^63 から 2^63-1 1_4