如何解决gcc 9.3.0 printf %Lf 输出不正确
printf("%Lf",long double)
将输出截断为 double
。还是我做错了什么?
Gcc 9.3.0 Ubuntu 20.04.2,Linux 5.8.0-59-generic
printf("print m_pi %.45f\n",M_PI);
printf("print m_pil %.45LF\n",M_PIl);
printf("maple Pi 3.141592653589793238462643383279502884197\n");
printf("m_pil def 3.141592653589793238462643383279502884L\n");
输出:
print m_pi 3.141592653589793115997963468544185161590576172
print m_pil 3.141592653589793238512808959406186204432742670
maple Pi 3.141592653589793238462643383279502884197
m_pil def 3.141592653589793238462643383279502884L
似乎 gcc printf
将 long double
截断为 13 位 +-。
解决方法
printf("%Lf",long double)
将输出截断为两倍
它显然不会截断任何内容。很容易看出 double
和 long double
的结果完全不同,long double
比 double
所以它没有任何问题。在 x86 上,long double
通常是 80-bit extended precision 类型,其精度为 around 18 digits,3.141592653589793238
正确到 19 位有效数字
如果您需要更高的精度,请通过设置 quadruple precision 选项使用 -mlong-double-128
或直接使用 __float128
。当然这是由软件模拟的,所以它会比原生 x87 80 位格式慢得多
要获得更高的精度,您必须使用第 3rd 方任意精度浮点库
为什么 size(long double)
是 16 个字节?
尺寸与精度无关。就像 C++ 中允许陷阱表示和填充位一样,类型的大小可以比实际精度更宽
在 80 位扩展格式中,内部表示是 10 个字节,但添加了填充字节以将类型对齐到 4 个字节 (x86) 或 8 个字节 (x86-64),从而在 64-位模式。可以通过 gcc
中的-m96/128bit-long-double
选项更改填充
此处重要的是 LDBL_DIG
/LDBL_MANT_DIG
/LDBL_MAX_EXP
/LDBL_MAX_10_EXP
或 std::numeric_limits<long double>::digits/digits10/max_exponent/max_exponent10
,它们是类型的真正精度。事实上,通过更改上述 -m-long-double
选项的组合,您会得到许多不同的结果:
-
-mlong-double-128
:大小 = 16,digits10 = 33,digits2 = 113 -
-m96bit-long-double
:大小 = 12,digits10 = 18,digits2 = 64 -
-mlong-double-64
:大小 = 8,数字 10 = 15,数字 2 = 53
默认结果是 size = 16、digits10 = 18、digits2 = 64。如果禁用填充,您将获得 size = 10,但由于未对齐,这会导致性能损失。在 Godbolt
上查看更多演示见
- Size of long double on Intel
- Why does a long double take up only 10 bytes in a string?
- sizeof long double and precision not matching?
在 PowerPC 中,您还可以看到 the same phenomena when changing the floating-point format。虽然大小仍然是 16 字节,但精度可能会有所不同。使用 -mabi=ibmlongdouble
(double-double arithmetic,这是默认值)你会得到 (size,digits10,digits2) = (16,31,106) 但是使用 -mabi=ieeelongdouble
元组将变成 (16,33,113)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。