【问题标题】:Converting from floating-point to decimal with floating-point computations使用浮点计算将浮点数转换为十进制数
【发布时间】:2013-07-16 14:57:27
【问题描述】:

我正在尝试将浮点双精度值x 转换为具有 12 个(正确舍入)有效数字的十进制。我假设x 介于 10^110 和 10^111 之间,因此它的十进制表示形式为x.xxxxxxxxxxxE110。而且,只是为了好玩,我只尝试使用浮点算术。

我来到下面的伪代码,其中所有运算都是双精度运算,符号1e98 是最接近数学 10^98 的双精度数,1e98_2 是最接近结果的双精度数数学减法 10^98-1e98。符号fmadd(X * Y + Z) 用于操作数XYZ 的融合乘加运算。

  y = x * 2^-1074;    // exact
  q = y / 1e98;       // q is denormal and the significand of q interpreted
                      // as an integer is our candidate for the 12 decimal
                      // digits of x

  r = fmadd(q * 1e98 - y);  // close to 1e98 * (error made during the division)

  // If 1e98_2 >= 0, we divided by a number that was smaller than we wished
  // The correct answer may be q or q+1.

  if (r and 1e98_2 have opposite signs)
  {
    return the significand of q;
  }

  s = copysign(2^-1074, r);
  r1 = abs(r);
  r2 = abs(1e98_2);

  h = 1e98 * 0.5 * 2^-1074;

  Set rounding mode to downwards

  r3 = fmadd(r2 * q + r1);

  if (r3 < h)
  {
    return the significand of q;
  }
  else
  {
    return significand of (q + s)
  }

对于上述伪代码造成的混乱,我深表歉意,但对我来说还不是很清楚,因此提出以下问题:

  1. 第一个 fmadd 是否按预期工作(计算 1e98 *(除法期间出错))?

  2. 标志。我无法说服自己他们是对的。但我也无法说服自己他们错了。

  3. 关于这个算法可能产生错误结果的频率有什么想法,也许是争论?

  4. 如果它确实有效,如果将“q = y / 1e98”更改为“q = y * 1e-98”(保持所有其他指令相同),算法是否有可能继续有效)?

我没有测试过这个算法。我没有任何带有 fmadd 指令的计算机,但我希望能找到一台以便执行上述操作。

【问题讨论】:

  • 你不能用 MPFR 来模拟 FMA 吗?

标签: floating-point ieee-754 fma


【解决方案1】:

y/d 为精确运算,q=rnd(y/d) 为四舍五入到最接近浮点数的结果。
那么真正的误差乘以 d 就是rt=(rnd(y/d)-y/d)*d=q*d-y 而我们用 fmadd 执行的操作就是r=rnd(q*d-y)
为什么q*d-y 是精确的(fmadd 没有最终舍入)不太清楚解释,但说q*d 的位数有限(&lt;nbits(q)+nbits(d)),y 的指数是q*d 的指数( +/- 1) 并且由于错误是 |rt|&lt;0.5*ulp(q)*d,这意味着第一个 nbits(q) 正在消失...这就是问题 1 的答案。

所以 q*1e98 - y = r ,其中 |r|*2^1074 &lt;= 0.5e98 &lt; 5*10^98 (第二个不等式是幸运的)

q*(10^98) - y = r + (10^98-1e98)*q where |10^98-1e98|*q*2^1074 &lt;= 0.5e95(假设精度至少为 15 位,log(2^53)/log(10) &gt; 15

所以你问|q*(10^98)-y|*2^1074&gt;5*10^97

您的近似值是 |q*(10^98)-y|,即 r+1e98_2*q

由于 |r| &lt; 5*10^98|r+(10^98-1e98)*q|&lt;|r| 如果符号相反,我认为这对问题 2 的回答是肯定的。但我不太确定 1e98_2 是否

如果r1e98_2 具有相同的符号,它可能会超过5*10^97,因此您可以进一步处理r3 = 1e98_2*q + rh=0.5e98*2^-1074 的讨论

对于问题 3,乍一看,我想说两件事可能会使算法失败:

  • 1e98_2 不准确(10^98-1e98-1e98_2 = -3.6e63 近似值)

  • h 不是ht=0.5*10^98*2^-1074,而是像我们上面看到的那样小一点。

真正的错误r3t 大约是(1e98_2-3e63)*q + r &lt; r3(只有 >0 的情况我们才感兴趣,因为 1e98_2>0)。

因此,当真实误差 r3t 低于真实关系 ht 时,误差 r3 的近似值落在近似关系 h 之上可能会导致不正确的舍入。有没有可能,如果有,您的问题 3 的频率如何?

为了减轻上述不平等风险,您尝试截断 r3 的大小,即r3 &lt;= 1e98_2*q + r。对错误界限进行真正的分析感到有点累...

所以我扫描错误,我发现的第一个失败的例子是1.0000000001835E110(我假设正确舍入到最接近的双倍,但实际上它实际上是1000000000183.499999995282256920120954969821120954969295546969826305469992112095469982C12095469982C1209544992C898442C192C120989992C830C840C1932C8446992C86084S66032C8442392C12C8466032S98)。 P>实际上是1.0000000001835E110

在这种情况下,r1e98_2 具有相同的符号,并且

  • (x/1e98) &gt; 1000000000183.50000215

  • q 有效位因此四舍五入为1000000000184

  • r3&gt;hr3*2^1074 约为 5.000001584620017e97)并且我们错误地增加了 q+s,而它应该是 q-s绝对是一个错误

我的答案是:

  1. 是的,r=fmadd(q * 1e98 - y) 正好是 1e98*(除法时出错),但我们不关心除法,它只是提供一个猜测,重要的是减法是准确的。

  2. 是的,符号是正确的,因为 |r| &lt; 5*10^98|r+(10^98-1e98)*q|&lt;|r| 如果符号相反。但我不太确定 1e98_2 是否

  3. 以第一个失败的例子(1.0000000001835e110 - 1.0e110)/1.0e110 ulp -&gt; 1.099632e6为例,一个非常天真的猜想是说百万分之一的情况下,r3 正在下降...所以一旦 q+s 纠正为 qs,发生的r3&gt;hr3t&lt;ht 在任何情况下都比1/1,000,000 小得多......在感兴趣的范围内有超过10 ^ 15个双打,所以认为这不是一个严肃的答案......

  4. 是的,上面的讨论仅仅是关于猜测 q,与它的产生方式无关,并且 1. 中的减法仍然是准确的......

【讨论】:

  • 感谢您调查我的问题,尽管它处于草稿状态。我认为我的最新计算机现在具有双精度 fmadd 指令,有了您的回答,我现在可以尝试将这个想法进一步推进。
猜你喜欢
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-08
  • 2014-11-24
  • 2011-08-11
  • 2016-06-01
  • 2016-04-02
相关资源
最近更新 更多