【问题标题】:What is required printf precision for a __float128 to not lose information?__float128 需要多少 printf 精度才能不丢失信息?
【发布时间】:2012-02-21 03:32:27
【问题描述】:

我正在尝试使用 libquadmath 打印 __float128,例如:

quadmath_snprintf(s, sizeof(s), "%.30Qg", f);

具有以下三个约束:

  1. 输出必须匹配以下产生式:

     number = [ minus ] int [ frac ] [ exp ]
    
     decimal-point = %x2E       ; .
    
     digit1-9 = %x31-39         ; 1-9
    
     e = %x65 / %x45            ; e E
    
     exp = e [ minus / plus ] 1*DIGIT
    
     frac = decimal-point 1*DIGIT
    
     int = zero / ( digit1-9 *DIGIT )
    
     minus = %x2D               ; -
    
     plus = %x2B                ; +
    
     zero = %x30                ; 0
    
  2. 假设任何输入 __float128 "i" 已打印到与上述产生式 "s" 匹配的字符串,然后 "s" 被扫描回 __float128 "j" - "i" 必须按位相同到“j” - 即不应丢失任何信息。至少对于某些值这是不可能的(NaN、Infinity),这些值的完整列表是什么?

  3. 应该没有其他字符串满足以上两个条件,即比候选字符串短。

是否有满足上述条件的 quadmath_snprintf 格式字符串(可能时为 1、3 和 2)?如果有,那是什么?

__float128 的哪些值不能通过上述产生式精确表示以满足第 2 点? (例如 Nan、+/-Infinity 等)如何检测 __float128 是否持有这些值之一?

【问题讨论】:

  • 在 __float128 中无法准确表示的十进制数是无限的。任何有效数字超过 34 位的数字。您的格式说明符会为任何 >= 1E5 的绝对数生成随机数字。您的方法存在严重缺陷,可能是从认为您需要 __float128 来解决问题开始的。
  • 在 __float128 中有无数个无法准确表示的十进制数这一事实无关紧要,第 2 点仅要求十进制表示足够精确,以便在回读和四舍五入时相同就像进去的一样。我知道格式说明符不正确,问题要求正确的格式说明符。我的“方法”很好,你不知道我要解决什么问题。

标签: c gcc floating-point glibc


【解决方案1】:

如果您使用的是 x86,那么 GCC __float128 类型是 IEEE 754-2008 binary128 格式的软件实现。如果字符表示包含 36 个有效(十进制)数字,则 IEEE 754 标准要求二进制 -> 字符 -> 二进制往返恢复原始值。因此格式字符串%.36Qg 应该这样做。

NaN 往返不需要恢复原始的按位值。

至于您的要求 #3,libquadmath 不包含这种“最短表示”格式的代码,例如本着 Steele & White paper 或 David Gay 的代码的精神。

【讨论】:

    【解决方案2】:

    我的直觉告诉我二进制分数 0.1111...1(128 个);也等于 1-1/2**128 将在转换为十进制时产生最大数量的溢出。将该值转换为十进制(我现在没有 bignum 包),计算位数,再加上 2-3,你应该是安全的。不过,我没有数学证明这已经足够了。

    如果 I/O 的精度很重要,我更喜欢将浮点数输出为十六进制字符串。准确的浮点 IO 很难做到正确,而且库在这方面可能存在问题。

    【讨论】:

    • “0.1111...1(128 个)”不能表示为 __float128,但即使将 128 固定为您可能的意思的 113,我不明白为什么这个数字应该是最坏的情况。最坏情况候选的十进制表示将以 1 开头,而不是 9 开头。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多