我想以std::cout
方式(GCC,clang,MSVC ++)打印一个double值,以便所有平台上的输出都相同。
我对指数的格式有问题。 以下程序
#include <iostream>
int main()
{
std::cout << 0.1e-7 << std::endl;
return 0;
}
此输出是否具有GCC:
1e-08
以及MSVC的以下输出
1e-008
如何使两个输出相同?
如果这是一个愚蠢的问题,我很抱歉,但到目前为止我还没有找到答案。 所有格式似乎都围绕着尾数之前的所有格式......
编辑:GCC的输出为1e-08
而非1e-8
(如最初所述),因此 符合要求。对不起,感到困惑。
EDIT2:在Dietmar的评论之后,实际上将“尾数”重命名为“指数”。 There also is a section on Wikipedia on mantissa vs. significant
答案 0 :(得分:11)
没有操纵者控制指数的格式(我假设你的意思是指数而不是尾数;而且,用于尾数的“官方”名称是显着)。更糟糕的是,我在C标准中看不到任何限制指数格式的规则。我意识到这是关于C ++的,但出于格式化细节的目的,C ++标准引用了C标准。
我唯一知道的方法是使用自己的std::num_put<char>
方面,根据需要格式化值。然后将此方面放入std::locale
,imbue()
依次std::cout
加入std::num_put<char>
。潜在的实现可以使用默认的snprintf()
方面(或{{1}},遗憾的是,可能更简单)来格式化浮点数,然后从指数中去除前导零。
答案 1 :(得分:3)
虽然Dietmar的答案是干净的,可能只是真正便携的答案,但我偶然发现了一个快速而肮脏的答案:
MSVC提供_set_output_format
函数,您可以使用该函数切换到“将指数打印为两位数”。
可以在main()
函数中实例化以下RAII类,以便为您提供与GCC,CLANG和MSVC相同的行为。
class ScientificNotationExponentOutputNormalizer
{
public:
unsigned _oldExponentFormat;
ScientificNotationExponentOutputNormalizer() : _oldExponentFormat(0)
{
#ifdef _MSC_VER
// Set scientific format to print two places.
unsigned _oldExponentFormat = _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
}
~ScientificNotationExponentOutputNormalizer()
{
#ifdef _MSC_VER
// Enable old exponent format.
_set_output_format(_oldExponentFormat);
#endif
}
};
答案 2 :(得分:2)
问题是Visual C ++没有遵循C99标准。在Visual C ++ 2015中,_set_output_format
被删除,因为编译器现在遵循标准:
%e
和%E
格式说明符将浮点数格式化为十进制尾数和指数。在某些情况下,%g
和%G
格式说明符也会格式化此表单中的数字。在以前的版本中,CRT将始终生成具有三位指数的字符串。例如,printf("%e\n", 1.0)
会打印1.000000e+000
。 这是不正确的:C要求如果只使用一个或两个数字表示指数,则只打印两个数字。在Visual Studio 2005中添加了全局一致性开关:
_set_output_format
。程序可以使用参数_TWO_DIGIT_EXPONENT
调用此函数,以启用符合指数的打印。 默认行为已更改为符合标准的指数打印模式。
见Breaking Changes in Visual C++ 2015。对于旧版本,请参阅@ Manuel的回答。
仅供参考,在C99 standard中,我们可以阅读:
选择e,E
表示浮点数的双参数在样式[ - ] d.ddd e(+ - )dd中转换,其中小数点前有一个数字(如果参数非零,则为非零)字符和后面的位数等于精度;如果精度丢失,则取6;如果精度为零且未指定#flag,则不显示小数点字符。该值四舍五入到适当的位数。 E转换说明符产生一个带E的数字而不是e引入指数。 指数始终包含至少两位数字,并且只包含表示指数所需的位数。如果该值为零,则指数为零。表示无穷大或NaN的双参数将以f或F转换说明符的样式进行转换。
与C90相比,这是一个差异,没有给出关于所需指数长度的任何指示。
请注意,最近的Visual C ++更改还涉及如何打印nan
,inf
等。