长双精度在 MinGW 上打印错误
Long double is printed incorrectly with iostreams on MinGW
考虑代码
#include <iostream>
int main() {
std::cout << 4.2L;
}
在 MinGW 上编译并运行它会产生以下输出:
> g++ test.cc
> a.exe
-7.89773e-278
这是MinGW中的错误吗,是否有修复或解决方法?
更新:
此问题中描述的printf
也存在类似的问题:
#include <cstdio>
int main() {
std::printf("%Lg", 4.2L); // prints -7.89773e-278
}
但是,printf
的问题可以通过定义__USE_MINGW_ANSI_STDIO
来解决,而这个不能,所以我认为它值得一个单独的问题。
这不是MinGW的错误...尽管这种说法看起来很有争议,但现实情况是,它是 MinGW 所依赖的 Microsoft C/C++ 运行时库的限制。作为开发人员,您有责任了解工具(例如此工具)的局限性,并在这些限制范围内工作。
您遇到的问题是由于 Microsoft 在 MSVC 中缺少对long double
数据类型的任何明显实现,因此在 MSVCRT.DLL 提供的 I/O 子系统中缺乏对该数据类型的有效支持;(而且,在您告诉我之前,也许是愤慨地告诉我"MSVC 当然支持long double
",我知道它在语法上确实如此,但在语义上它没有明显的实现,只是通过有效地忽略long
限定符来表现,因此long double
成为裸double
的同义词)。
相反,GCC和MinGW确实有一个long double
的实现,这与double
不同;前者是一个80位的实体,而后者是64位的,并且是MSVC两种数据类型的64位实现的精确类似物。当您需要更高精度的 80 位浮点计算时,这非常有用,但在结果输出方面可能会导致问题,例如您正在遇到的问题;(I/O 转换器将获得long double
数据实体的 80 位原始数据表示形式,它期望 64 位;内部表示形式不兼容,因此当尾数的一部分被解释为指数时,垃圾随之而来)。
正如你所注意到的,虽然MSVCRT.DLL仅支持64位double
值的输出,但MinGW确实提供了C的printf
样式I/O的替代实现,它可以正确转换80位格式;但是,这并不扩展到支持C++样式I/O。因此,在C++代码中,您不能简单地利用 MinGW 替代 I/O 实现,同时继续使用 C++ I/O 语义;您必须认识到 MSVCRT.DLL 限制,并相应地对应用程序进行编码。您可以考虑的一些选项包括:--
- 放弃使用
long double
数据类型,并按double
执行计算;(这是Microsoft编译器用户有效使用的唯一选项,因为它实际上没有明显的long double
数据类型实现)。 - 按
long double
执行计算,但将结果转换为double
进行输出。
使用 C 样式的 I/O - 函数代替C++ I/O 语义,并通过编译
-posix
、-D_GNU_SOURCE
、-D_BSD_SOURCE
、-D_XOPEN_SOURCE=700
或-D_POSIX_C_SOURCE=200809L
中的任何一个来启用 MinGW 的替代printf
实现(或者更好的是,在任何#include
之前将后四个中的任何一个#define
中的任何一个添加到您的源中)。 如果愿意,您也可以用任何较早的合规级别代替_XOPEN_SOURCE
或_POSIX_C_SOURCE
;(但是,请忽略一些评论员可能提供的令人难以置信的糟糕建议,即使用-D__USE_MINGW_ANSI_STDIO
进行编译;引入该宏名称的双下划线将其标记为"保留的实现",因此您作为编译器实现的最终用户不应该直接引用)。
使用 C 的 snprintf
函数将long double
数据转换为 C 字符串表示形式,然后使用C++语义输出该表示形式,而不是让C++直接翻译long double
实体的原始形式。(IIRC,Microsoft不提供snprintf
- 而是提供_snprintf
- 因此,如果您小心使用ANSI函数名称,则会自动获得80位long double
支持)。
- 为什么没有打印错误消息
- 插入排序打印错误的输出
- 当我输入一个字母时,cin 输入(输入是一个 int),而不是打印错误一次,它打印正确一次,然后在循环的其余部分打印 i
- 使用使用运算符<<并打印错误值 c++ 的类进行编程
- cLion & cMake 不调试/打印错误
- 如何使用适用于 Lua 的 C API 在控制台中打印错误
- 为什么我的代码打印错误的密文
- 声明数组和打印[错误?]
- 为什么在这种情况下打印错误
- q调试打印错误的数字
- 阿姆斯特朗数字打印错误
- C++ 链表打印错误
- 长双精度在 MinGW 上打印错误
- C++ <ctime> 打印错误的日期
- 用"fprintf"打印错误后调用"getchar()"有什么意义?
- C++类型包装器 printf 打印错误的浮点值
- 如何让犰狳函数在反转奇异矩阵时不打印错误
- 缩短的数组打印错误的结果
- 打印错误的链表c++
- cout 中的打印错误