格式化浮点值:返回默认值

Formatting floats: returning to default

本文关键字:返回 默认值 格式化      更新时间:2023-10-16

从返回"默认格式"的意义上讲,我遇到了浮点值的格式化问题。假设我有两个浮动:

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

设置精度(和"固定"(:

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

将显示:444.00 - 444.50

但回归"默认":

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

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

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

FWIW,实时代码在这里。

编辑:此问题已被标记为重复,但链接的答案不会提供该问题的答案,它只提到如何获得当前精度。

编辑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

在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还没有广泛可用,但同时您可以使用std::format所基于的{fmt}库。它还提供了一个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++20std::format的作者。

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

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

或者,您可以在操作之前保存整个流状态,并在操作之后恢复;请参阅此线程。

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

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

固定格式应用精度,n是小数点后的位数。defaultfloat格式将精度应用为要显示的最大总位数。

它不会重置精度值。

供参考:ios_base::精度

您只需在原始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