Rag*_*jar 63 c c++ floating-point precision numbers
我在C中有这个代码,我已经宣布0.1为double.
#include <stdio.h>
int main() {
double a = 0.1;
printf("a is %0.56f\n", a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这就是它的印刷品, a is 0.10000000000000001000000000000000000000000000000000000000
C++中的代码相同,
#include <iostream>
using namespace std;
int main() {
double a = 0.1;
printf("a is %0.56f\n", a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这就是它的印刷品, a is 0.1000000000000000055511151231257827021181583404541015625
有什么不同?当我读到两个都被分配8个字节?C++如何在小数位上打印更多数字?
另外,它怎么能到小数点55位?IEEE 754浮点只有52位的小数,我们可以得到15位十进制数的精度.它以二进制形式存储.为什么它的十进制解释存储更多?
Che*_*Alf 80
使用MinGW g ++(和gcc)7.3.0,您的结果将被准确复制.
这是一个非常奇怪的未定义行为案例.
未定义的行为是由于使用时printf没有包含适当的标题,¹违反"应该"
"翻译单位应仅在任何声明或定义之外包括标题,并且应在该翻译单位的第一次参考之前以词汇方式将标题包括在该标题中声明的任何实体之前.无需诊断.
在C++代码中更改<iostream>为<stdio.h>,以获取有效的C++代码,并获得与C程序相同的结果.
为什么C++代码甚至可以编译?
好吧,与C不同,在C++中,允许标准库头在任何其他头中拖动.显而易见,使用g ++ <iostream>标题拖延了一些声明printf.只是不完全正确.
详细信息:使用MinGW g ++ 7.3.0时,声明/定义printf取决于宏符号__USE_MINGW_ANSI_STDIO.默认就是<stdio.h>声明printf.但是当__USE_MINGW_ANSI_STDIO定义为逻辑真时,<stdio.h>提供printf调用的重写定义__mingw_vprintf.并且在发生之前,<cstdio>标题__USE_MINGW_ANSI_STDIO在包含之前定义(通过间接包含)<stdio.h>.
有一条评论<_mingw.h>,"请注意,我们也在C++中为_GNU_SOURCE启用它,但不支持C情况."
在C++中,使用此编译器的相关版本,包含<stdio.h>和使用printf,包括<cstdio>,说using std::printf;和使用之间实际上存在差异printf.
关于
"另外,它怎么能到小数点55位?IEEE 754浮点只有52位的小数,我们可以得到15位十进制数的精度.它以二进制形式存储.为什么它的十进制解释存储更多?
...这只是小数表示更长.超出内部表示精度的数字,对于64位IEEE 754约为15位,基本上是垃圾,但它们可以用于精确地重构原始位.在某些时候,它们将变为全零,并且达到C++程序输出中最后一位的那一点.
1感谢Dietrich Epp发现标准报价.
MSa*_*ers 10
在我看来,两种情况都打印56位小数,所以问题在技术上是基于一个有缺陷的前提.
我也看到两个数字都等于0.152位精度,所以两者都是正确的.
这导致了你的最后一个问题,"它的十进制解释如何存储更多?".它不存储更多小数.double不存储任何小数.它存储位.生成小数.