gcc - 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
似乎 gccprintf
正在截断long double
为 13 位数字 +-。
解决方案
printf("%Lf", long double)
将输出截断为两倍
它显然不会截断任何内容。很容易看到结果,double
并且long double
完全不同,并且long double
比double
所以这没有什么问题。在 x86long double
上通常是80 位扩展精度类型,其精度约为 18 位,并且3.141592653589793238
对 19 位有效数字是正确的
如果您需要更高的精度,则通过设置选项或直接使用来使用四倍精度。当然这是由软件模拟的,因此它会比原生 x87 80 位格式慢得多-mlong-double-128
__float128
要获得更高的精度,您必须使用 3 rd方任意精度浮点库
为什么是
size(long double)
16 字节?
尺寸与精度无关。就像 C++ 中允许的陷阱表示和填充位一样,类型的大小可以比实际精度更宽
在 80 位扩展格式中,内部表示为 10 字节,但添加了填充字节以将类型对齐为 4 字节 (x86) 或 8 字节 (x86-64),从而在 64 位模式下产生 16 字节类型。可以通过-m96/128bit-long-double
gcc 中的选项更改填充
这里重要的是///或者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,数字 10 = 33,数字 2 = 113-m96bit-long-double
:大小 = 12,数字 10 = 18,数字 2 = 64-mlong-double-64
: 大小 = 8,digits10 = 15,digits2 = 53
默认结果是 size = 16, digits10 = 18, digits2 = 64。如果禁用填充,您将得到 size = 10,但由于未对齐,这会以性能为代价。在Godbolt上查看更多演示
看
在 PowerPC 中,您也可以在更改浮点格式时看到相同的现象。虽然大小仍然是 16 字节,但精度可能会有所不同。使用-mabi=ibmlongdouble
(双双算术,这是默认值)您将得到 (size, digits10, digits2) = (16, 31, 106) 但-mabi=ieeelongdouble
元组将变为 (16, 33, 113)
推荐阅读
- c# - 将空参数传递给存储过程
- python-3.x - 如何在 Python 中允许在没有类名的情况下从外部访问类属性?
- machine-learning - 有没有什么快速又好的方法来为机器学习模型创建仪表板?
- java - Apache spark 在循环中卡住了。我究竟做错了什么?
- machine-learning - 自动编码器:找到重要的神经元
- gps - 如何仅使用 GPS 数据识别公交车站?
- python-3.x - 使用python解析浏览器发出的请求
- c# - 如何将 UTF16LE 转换为字符串 C#?
- react-native - 世博会不会启动新项目
- java - 无法触发构造函数级别验证