std::cout如何输出浮点数

18

我正在使用 Visual Studio 2015 打印两个浮点数:

double d1 = 1.5;
double d2 = 123456.789;

std::cout << "value1: " << d1 << std::endl;
std::cout << "value2: " << d2 << std::endl;

std::cout << "maximum number of significant decimal digits (value1): " << -std::log10(std::nextafter(d1, std::numeric_limits<double>::max()) - d1) << std::endl;
std::cout << "maximum number of significant decimal digits (value2): " << -std::log10(std::nextafter(d2, std::numeric_limits<double>::max()) - d2) << std::endl;

这将打印以下内容:

value1: 1.5
value2: 123457
maximum number of significant decimal digits (value1): 15.6536
maximum number of significant decimal digits (value2): 10.8371

当值为123456.789时,为什么会输出123457?在没有使用std::setprecision()的情况下,ANSI C++规范是否允许在使用std::cout时显示浮点数的任何内容?


4
ANSI C++规范允许在使用std::cout但没有使用std::setprecision()的情况下显示浮点数吗?是的,允许。 - Mats Petersson
@Hermantas,对,我的意思是std::cout。 - Daniel Laügt
@Mats,为什么在这个主题上规范那么模糊?如果规范更具体(例如打印浮点数及其有效数字),将有助于开发人员。类似printf("%.16g\n", d)这样的东西。 - Daniel Laügt
1
默认精度为6,就像printf一样。 - Bo Persson
@Bo,正确的std::cout.precision()输出结果为6,因此规范已经定义得很好了。谢谢。 - Daniel Laügt
3个回答

12

四舍五入是由于C++标准引起的,可以通过编写以下代码查看:std::cout<<std::cout.precision();

输出屏幕将显示6,这表示std::cout语句将打印的默认有效数字数为6。这就是为什么它会自动将浮点数四舍五入到6位小数的原因。


12

你所指出的实际上是C++中标准输入输出流(standard iostream)委员会应该考虑的众多问题之一。当你写代码时,这些东西工作得很好:

printf ("%f\n", d2);

但是在使用std::cout时,你需要使用std::setprecision,因为它的格式类似于在printf中使用%g而不是%f。所以你需要写:

std::cout << std::setprecision(10) << "value2: " << d2 << std::endl;

但是,如果您不喜欢这种方法,并且正在使用C++11(及以后版本),那么您也可以编写:

std::cout << "value2: " << std::to_string(d2) << std::endl;

这将给您与printf("%f\n", d2)相同的结果。

一个更好的方法是通过使用std::fixed来取消在std::cout中发生的舍入:

#include <iostream>
#include <iomanip>
int main()
{
    std::cout << std::fixed;
    double d = 123456.789;
    std::cout << d;
    return 0;
}

输出:

123456.789000

所以我猜你的问题已经解决了!


正确的做法是,printf("%f", d)会显示一个带有6位小数的浮点数。std::cout会显示一个最多有6位数字(包括小数点前后的数字)的浮点数。我之前不知道这个默认精度,所以感到困惑。现在一切都清楚了...谢谢。 - Daniel Laügt
有趣的是,我没有意识到传递给 printf 的浮点参数实际上是双精度。 - Juan

3
我认为这里的问题在于C++标准并非易于阅读,而是旨在精确和不重复。因此,如果您查找operator<<(double),它除了“它使用num_put-因为这就是如何实现cout<<some_float_value”之外什么也没有说。

默认行为就是print("%g", value);所做的[表88在C++标准n3337版本中解释了printf和c++格式的等价性]。因此,如果您想要 %.16g,您需要通过调用setprecision(16)来更改精度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接