虽然long double提供了更高的精度和更大的范围,但它的兼容性和移植性不好。不同的编译器和平台对long double的实现有所不同。因此,在跨平台开发时,使用long double需要特别小心,确保在所有目标平台上都能正确运行。
long double类型sizeof()实测:存储空间
测试代码:
int main() | |
{ | |
std::cout << sizeof(long double) << std::endl; | |
return 0; | |
} |
- g++.exe (MinGW-W64 x86_64-posix-seh, built by Brecht Sanders) 11.3.0: 16 (128bits)
- c++Builder12.2
- bcc32c(基于clang5): 10 (80bits)
- bcc64x(基于clang15,使用
-mlong-double-128
):8 (64bits)
- VC++,微软的long double 就是double,只有64位:https://learn.microsoft.com/zh-cn/cpp/build/ieee-floating-point-representation?view=msvc-140
- clang
- 为了处理和windows的新的sdk的兼容性问题,clang的新版本(15)竟然把
-mlong-double-128
选项给移除了,统一性做的并不好: https://github.com/flang-compiler/flang/pull/1340 - 一位c++Builder用户抱怨 Clang (无论主机是什么) 不实现使用 quadmath 128 位浮点库,即使已经为此自己做了很多工作: https://github.com/boostorg/multiprecision/issues/216
- 为了处理和windows的新的sdk的兼容性问题,clang的新版本(15)竟然把
用圆周率测试long double
测试代码:
int main() | |
{ | |
std::cout << "sizeof(long double):"<<sizeof(long double) << std::endl; | |
// PI,有效十进制位数40,对应的字符串 | |
std::string str_pi = "3.141592653589793238462643383279502884197"; | |
//测试long double 的变量,需要转为对应的字符串 | |
long double pi=3.141592653589793238462643383279502884197L; | |
std::ostringstream out; | |
out.precision(39); | |
out << std::fixed << pi; | |
//long double类型 pi 对应的字符串 | |
std::string str_pi_from_long_double = out.str(); | |
std::cout <<"pi: "<< str_pi << std::endl; | |
std::cout <<"pi_from_long_double:"<< str_pi_from_long_double << std::endl; | |
//计算long double 精度 | |
int n=2;//精度 | |
while(n<40) { | |
if (str_pi[n]!=str_pi_from_long_double[n]) { | |
std::cout << "The number of significant digits in long double is:" <<n-1<< std::endl; | |
break; | |
}else { | |
n++; | |
} | |
} | |
} |
g++:
sizeof(long double):16 | |
pi: 3.141592653589793238462643383279502884197 | |
pi_from_long_double:3.141592653589793238512808959406186204433 | |
The number of significant digits in long double is:19 ` |
bcc32c:
sizeof(long double):10 | |
pi: 3.141592653589793238462643383279502884197 | |
pi_from_long_double:3.141592653589793238000000000000000000000 | |
The number of significant digits in long double is:19 |
bcc64x:
sizeof(long double):8 | |
pi: 3.141592653589793238462643383279502884197 | |
pi_from_long_double:3.141592653589793115997963468544185161591 | |
The number of significant digits in long double is:16 |
结果:
- bcc32c:用80位存储19位有效数字的pi
- g++ :用 128位存储pi,但只有19位有效
- bcc64x:用64位存储pi
如果传一个double(字面量末尾没有加L):
long double pi=3.141592653589793238462643383279502884197;
g++:
pi: 3.141592653589793238462643383279502884197 | |
pi_from_long_double:3.141592653589793115997963468544185161591 | |
The number of significant digits in long double is:16 |
bcc32c:
sizeof(long double):10 | |
pi: 3.141592653589793238462643383279502884197 | |
pi_from_long_double:3.141592653589793116000000000000000000000 | |
The number of significant digits in long double is:16 |
bcc64x:
sizeof(long double):8 | |
pi: 3.141592653589793238462643383279502884197 | |
pi_from_long_double:3.141592653589793115997963468544185161591 | |
The number of significant digits in long double is:16 |
long double相关参考资料
- 真正的四精度浮点数可能要使用
__float128
: Floating Types (Using the GNU Compiler Collection (GCC)) - x86 64pc一般实现的是80位long double: 扩展精度 – 维基百科,自由的百科全书
- 实现:x86 体系结构(特别是 x86 上的 x87 浮点指令)支持 80 位扩展精度运算,在 GNU C 编译器中,无论用于该类型的物理存储如何(可以是 96 位或 128 位),在 x86 处理器上都是 80 位扩展精度:long double – 维基百科,自由的百科全书
- IEEE 浮点运算标准 (IEEE 754) 是浮点运算的技术标准,最初由电气和电子工程师协会 (IEEE) 于 1985 年制定。该标准解决了在各种浮点实现中发现的许多问题,这些问题使它们难以可靠和可移植地使用。许多硬件浮点单元使用 IEEE 754 标准:IEEE 754 – 维基百科,自由的百科全书
正文完