c - 如何打印浮点值以供以后以完美的精度进行扫描?

标签 c floating-point precision numeric

假设我有一个 float 类型的浮点值或 double (即典型机器上的 32 或 64 位)。我想将此值打印为文本(例如打印到标准输出流),然后在其他一些过程中将其扫描回 - 使用 fscanf()如果我使用 C 语言,或者可能使用 istream::operator>>()如果我使用 C++。但是 - 我需要扫描的浮点数最终与原始值完全相同(直到相同值的等效表示)。此外,打印的值应该很容易阅读 - 对人类来说 - 作为浮点数,即我不想打印 0x42355316 并将其重新解释为 32 位浮点数。
我该怎么做?我假设(C 和 C++)的标准库是不够的,但也许我错了。我想足够数量的十进制数字可能能够保证低于精度阈值的错误 - 但这与保证舍入/截断会按照我想要的方式发生不同。
笔记:

  • 扫描不必完全准确w.r.t。它扫描的值,只有原始值。
  • 如果它更容易,您可以假设该值是一个数字而不是无穷大。
  • 非正常支持是需要的,但不是必需的;如果我们得到一个异常,失败应该是显而易见的。
  • 最佳答案

    首先,您应该使用 %a格式为 fprintffscanf .这就是它的设计目的,如果实现使用二进制浮点数,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 ,其中 Typefloatdouble或其他浮点类型。
    请注意,C 标准仅建议通过十进制数字进行此类往返;它不需要它。例如,C 2018 5.2.4.2.2 15 在“推荐做法”标题下说:

    Conversion from (at least) double to decimal with DECIMAL_DIG digits and back should be the identity function. [DECIMAL_DIG is the equivalent of FLT_DECIMAL_DIG or DBL_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/

    相关文章:

    c - 使用指针在c中反转字符串

    c++ - 在 C/C++ 中按位指定浮点常量值

    c++ - cout 打印 "-0"而不是 "0"

    java - 如何防止小数除法时精度损失?

    C++ 不截断 double ?

    c - 字符串比较 C - strcmp()

    c - 反汇编代码中的可读文本

    c - 如何在使用文件重定向时访问默认的标准输入?

    python - Delphi - 映射函数意外输出

    c - 'zero of the function will be found within the precision limit ϵ = 10 - 3' 这意味着什么?