假设我有一个 float
类型的浮点值或 double
(即典型机器上的 32 或 64 位)。我想将此值打印为文本(例如打印到标准输出流),然后在其他一些过程中将其扫描回 - 使用 fscanf()
如果我使用 C 语言,或者可能使用 istream::operator>>()
如果我使用 C++。但是 - 我需要扫描的浮点数最终与原始值完全相同(直到相同值的等效表示)。此外,打印的值应该很容易阅读 - 对人类来说 - 作为浮点数,即我不想打印 0x42355316 并将其重新解释为 32 位浮点数。
我该怎么做?我假设(C 和 C++)的标准库是不够的,但也许我错了。我想足够数量的十进制数字可能能够保证低于精度阈值的错误 - 但这与保证舍入/截断会按照我想要的方式发生不同。
笔记:
最佳答案
首先,您应该使用 %a
格式为 fprintf
和 fscanf
.这就是它的设计目的,如果实现使用二进制浮点数,C 标准要求它工作(重现原始数字)。
否则,您应该打印 float
至少 FLT_DECIMAL_DIG
有效数字和 double
至少 DBL_DECIMAL_DIG
有效数字。这些常量在 <float.h>
中定义并定义为:
… number of decimal digits, n, such that any floating-point number with p radix b digits can be rounded to a floating-point number with n decimal digits and back again without change to the value,… [b is the base used for the floating-point format, defined in
FLT_RADIX
, and p is the number of base-b digits in the format.]
例如:
printf("%.*g\n", FLT_DECIMAL_DIG, 1.f/3);
或者:#define QuoteHelper(x) #x
#define Quote(x) QuoteHelper(x)
…
printf("%." Quote(FLT_DECIMAL_DIG) "g\n", 1.f/3);
在 C++ 中,这些常量在 <limits>
中定义。如 std::numeric_limits<Type>::max_digits10
,其中 Type
是 float
或 double
或其他浮点类型。请注意,C 标准仅建议通过十进制数字进行此类往返;它不需要它。例如,C 2018 5.2.4.2.2 15 在“推荐做法”标题下说:
Conversion from (at least)
double
to decimal withDECIMAL_DIG
digits and back should be the identity function. [DECIMAL_DIG
is the equivalent ofFLT_DECIMAL_DIG
orDBL_DECIMAL_DIG
for the widest floating-point format supported in the implementation.]
相反,如果您使用
%a
, 和 FLT_RADIX
是 2 的幂(意味着实现使用的是 2、16 或 2 的另一个幂的浮点基数),那么 C 标准要求扫描由 %a
产生的数字的结果。等于原来的数字。
关于c - 如何打印浮点值以供以后以完美的精度进行扫描?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62982132/