我需要打印一个IEEE 64位的 double
作为十六进制字符串。
我知道我必须用 std::hexfloat
以某种方式。但是,如何在这之前就得到流的状态,从而将其复位到初始状态呢?
如果目标是以尽可能高的精度来打印的话,是否也必须黑掉精度?还是说这已经是hexfloat的一个特性?
输出的方式必须是可以在CC++源码中使用的,而不需要再多说什么,如 -0x123.abc42p+10
.
我使用的语言是C++11,不多不少。
但如何在这之前得到流的状态,使它可以被重置到初始状态?
你可以使用流的 flags()
功能来检索和保存当前设置,然后再使用 setf()
函数来恢复它们,并确保包括 std::ios_base::floatfield
中的 "掩码"(第二个参数)。
如果目标是以尽可能高的精度来打印,精度是否也必须被破解?还是说这已经是hexfloat的一个特性?
是的。从 cppreference:
十六进制浮点格式化忽略了流精度的规定,这是std::num_put::do_put的要求。
这里有一个简短的演示程序,可能会有帮助。
#include <iostream>
using std::cout; using std::endl;
int main()
{
double test = -0x123.abc42p+10;
cout << std::fixed; // Change from the default for demo
cout << test << endl; // Display in "Current" format
auto fSave = cout.flags(); // Save current flags
cout << std::hexfloat; // Change to HEX float
cout << test << endl; // ... and display
cout.setf(fSave, std::ios_base::floatfield); // Restore float field
cout << test << endl; // Restored to previous settings!
return 0;
}
我所需要的这个项目使用的东西比C++11多一些,也就是 GMP 它支持打印修饰符 %a
从C99开始。
// Include cstdarg / stdarg.h prior to gmp.h in the case
// we want va_list functions like gmp_vfprintf.
#include <cstdarg>
#include <gmp.h>
void func (double d)
{
gmp_printf ("%a", d);
}
#include <iostream>
void func (std::ostream& ost, double d)
{
auto len = gmp_snprintf (nullptr, 0, "%a", d);
char str[1 + len];
gmp_sprintf (str, "%a", d);
ost << str;
}