格式化浮动:返回默认值

Formatting floats: returning to default

我 运行 陷入了浮点值的格式化问题,就返回到 "default formatting" 而言。 假设我有 2 个花车:

float f1 = 3.0f, f2 = 1.5f;
std::cout << f1 << " - " << f2 << "\n";

将显示为:3 - 1.5

现在,出于某种原因,我需要在 std::cout 上设置精度(用于其他打印):

cout << std::precision(2);

如果我再次打印我的两个浮点数,这将导致:3.00 - 1.50

现在我想恢复默认格式。在 C++11 之前,这似乎很困难(或者是吗?)。但是,谢谢,我现在有了这个新标志: std::defaultfloat。让我们试试:

std::cout << std::defaultfloat << f1 << " - " << f2;

将打印:3 - 1.50。很好。

哦,等等。假设我有:

float f1 = 444.0f, f2 = 444.5f;

默认打印会显示:444 - 444.5

设置精度(和"fixed"):

cout << std::precision(2) << std::fixed;

将显示:444.00 - 444.50

但回到"default":

std::cout << std::defaultfloat << f1 << " - " << f2;

将打印:4.4e+02 - 4.4e+02(自动切换到科学格式)。而且,如果您想知道,附加 "fixed" 标志将保持先前指定的精度,因此不会返回到原始设置。

问题:如何回到默认模式?

FWIW,live code is here

Edit: 这个问题已经被标记为一个骗子但是 linked answer 没有提供问题的答案,它只提到如何获得当前的精度.

编辑 2:根据要求,这里是演示问题的完整代码:

int main()
{
    float f1 = 444.5f, f2=443.0f;
    std::cout << f1 << " - " << f2 << "\n";
    std::cout << std::fixed << std::setprecision(2);
    std::cout << f1 << " - " << f2 << "\n";
    std::cout << std::defaultfloat;
    std::cout << f1 << " - " << f2 << "\n";
}

结果:

444.5 - 443
444.50 - 443.00
4.4e+02 - 4.4e+02

std::precision指定cout显示的精度,当你改变格式时它不会改变。

因此,当您设置 std::precision(2) 时,它指定以下所有格式都将应用该精度显示。

fixed 格式应用精度,因为 n 是小数点后的位数。 默认浮点格式应用精度作为要显示的最大总位数。

它不会重置精度值。

供参考: ios_base::precision

std::defaultfloat 不会重置精度。 (不要问我为什么)。您可以将其重置为默认值,即定义为 6:

std::cout << std::defaultfloat << std::setprecision(6) << f1 << " - " << f2;

或者你可以在操作之前保存整个流状态并在之后恢复它;请参阅 this thread

在 C++20 中,您可以使用 std::format,这是一个无状态的 API。特别是,在一个调用中指定精度不会影响另一个调用:

float f1 = 444.0f, f2 = 444.5f;
std::cout << std::format("{} - {}\n", f1, f2);
// Output: 444 - 444.5
std::cout << std::format("{:.2f} - {:.2f}\n", f1, f2);
// Output: 444.00 - 444.50
std::cout << std::format("{} - {}\n", f1, f2);
// Output: 444 - 444.5

std::format 尚未广泛使用,但您可以使用 the {fmt} library,同时 std::format 是基于它的。它还提供了一个 print 功能,结合了格式化和 I/O:

float f1 = 444.0f, f2 = 444.5f;
fmt::print("{} - {}\n", f1, f2);
// Output: 444 - 444.5
fmt::print("{:.2f} - {:.2f}\n", f1, f2);
// Output: 444.00 - 444.50
fmt::print("{} - {}\n", f1, f2);
// Output: 444 - 444.5

免责声明:我是 {fmt} 和 C++20 的作者 std::format

您可以简单地在原始 std::ostreamstd::streambuf 上创建您自己的 std::ostream,并在这个新的个人 std::ostream 上设置格式。

#include <iostream>
#include <ostream>
#include <iomanip>

float const f1 = 3.0f, f2 = 1.5f;

void proc1() {
    std::ostream out(std::cout.rdbuf());
    out << "Inside proc1(), floats are printed like: " << std::setprecision(2) << std::fixed << f1 << " and " << f2 << '\n';
}

int main() {
    std::cout << "Inside main(), floats are printed like: " << f1 << " and " << f2 << '\n';
    proc1();
    std::cout << "Back in main(), floats are printed like: " << f1 << " and " << f2 << '\n';
}

此代码将打印:

Inside main(), floats are printed like: 3 and 1.5
Inside proc1(), floats are printed like: 3.00 and 1.50
Back in main(), floats are printed like: 3 and 1.5

你可以在那里试试:http://coliru.stacked-crooked.com/a/4994c3f604b63d67

基于另一个 std::streambuf 创建 std::ostream 是正确的,因为 std::ostream 的析构函数不会触及其分配的 std::streambuf。参见:https://en.cppreference.com/w/cpp/io/basic_ostream/%7Ebasic_ostream