3

如果您打印的浮点数比存储在内存中的精度更高,那么额外的地方不应该在其中包含零吗?我有这样的代码:

double z[2*N]="0";
...
for( n=1; n<=2*N; n++) {
  fprintf( u1, "%.25g", z[n-1]);
  fputc( n<2*N ? ',' : '\n', u1);
}

正在创建这样的输出:

0,0.7071067811865474617150085,....

浮点数应该只有 17 位小数(对吗?53 位不是 17 位小数)。如果是这样,那么第 18 位、第 19 位……第 25 位应该是零。请注意,在上面的输出中,它们中的数字不是 0。

我是不是误会了什么?如果是这样,是什么?

4

4 回答 4

7

不,53 位意味着 17 位小数是您可以信任的,但是因为我们使用的 base-10 表示法与存储双精度数的基数不同(二进制),所以后面的数字只是因为 1/2^ 53 不完全是 1/10^n,即

1/2^53 = .0000000000000001110223024625156540423631668090820312500000000

于 2012-12-07T09:29:38.270 回答
4

您的实现打印的字符串显示了示例中双精度的确切值,这是 C 标准允许的,如下所示。

首先,我们应该了解浮点对象代表什么。C 标准在这方面做得很差,但是,假设您的实现使用 IEEE 754 浮点标准,正常的浮点对象恰好表示(-1) s •2 e •(1+f) 用于某些符号位s(0 或 1)、指数 e(在特定类型的范围内,双精度为 -1022 到 1023)和小数 f(也在范围内,双精度小数点后的 52 位)。许多人使用对象来近似附近的值,但根据标准,对象仅代表它定义的一个值。

您显示的值 0.7071067811865474617150085 可以完全表示为双精度(符号位 0、指数 -1 和小数位 [十六进制] .6a09e667f3bcc 16)。重要的是要了解具有此值的双精度值恰好代表该值;它不代表附近的值,例如 0.707106781186547461715。

现在我们知道传递给 的值fprintf,我们可以考虑 C 标准对此有何规定。首先,C 标准定义了一个名为 DECIMAL_DIG 的常量。C 2011 5.2.4.2.2 11 将其定义为小数位数,以便最广泛支持的类型中的任何浮点数都可以四舍五入到那么多十进制数字并再次返回而无需更改值。您传递给fprintf25 的精度可能大于系统上 DECIMAL_DIG 的值。

在 C 2011 7.21.6.1 13 中,标准规定“如果有效十进制数字的数量超过 DECIMAL_DIG 但源值可以用 DECIMAL_DIG 数字精确表示,那么结果应该是带有尾随零的精确表示。否则,源值由两个相邻的十进制字符串 L < U 限定,两者都具有 DECIMAL_DIG 有效数字;得到的十进制字符串 D 的值应满足 L ≤ D ≤ U,并额外规定误差应具有当前舍入方向的正确符号。”</p>

这种措辞允许编译器有一些回旋余地。目的是结果必须足够准确,以便可以无错误地转换回原始双精度。它可能更准确,并且某些 C 实现将产生完全正确的值,这是允许的,因为它满足上面的段落。

顺便说一句,您显示的值不是最接近 sqrt(2)/2 的两倍。该值为 +0x1.6A09E667F3BCDp-1 = 0.70710678118654757273731092936941422522068023681640625。

于 2012-12-07T12:24:52.720 回答
0

有足够的精度来表示0.7071067811865474617150085精度浮点数。64位输出其实是3FE6A09E667F3BCC

用于计算数字的公式是取幂,因此您不能说53位将采用17小数位。

编辑:在 wiki 文章中查看下面的示例以获取另一个实例:

 0.333333333333333314829616256247390992939472198486328125
=2^(−54) × 15 5555 5555 5555 base16
=2^(−2) × (15 5555 5555 5555 base16 × 2^(−52) )
于 2012-12-07T09:31:56.877 回答
0

您要求浮动,但在您的代码中出现双倍。

无论如何,浮点数或双精度数都不总是相同的小数位数。根据 IEEE 754,浮点数为浮点表示分配了 32 位(4 个字节)。

来自维基百科

浮点表示

IEEE 754 标准将 binary32 指定为:

  • 符号位:1位
  • 指数宽度:8位
  • 有效精度:24(23 显式存储)

这给出了 6 到 9 位有效小数位的精度(如果将具有最多 6 个有效小数位的十进制字符串转换为 IEEE 754 单精度,然后转换回相同的有效小数位数,则最终字符串应与原始字符串匹配;和如果将 IEEE 754 单精度转换为具有至少 9 位有效小数的十进制字符串,然后再转换回单精度,则最终数字必须与原始数字匹配)。

在双重的情况下,再次来自维基百科

双重代表

双精度二进制浮点是 PC 上常用的格式,因为它比单精度浮点范围更广,尽管它的性能和带宽成本。与单精度浮点格式一样,与相同大小的整数格式相比,它在整数上缺乏精度。它通常被简单地称为双重。IEEE 754 标准将 binary64 指定为:

  • 符号位:1位
  • 指数宽度:11 位
  • 有效位精度:53 位(显式存储 52 位)

这给出了 15 - 17 位有效十进制数字的精度。如果将最多 15 位有效小数的十进制字符串转换为 IEEE 754 双精度,然后再转换回相同的有效小数位数,则最终字符串应与原始字符串匹配;如果 IEEE 754 双精度转换为具有至少 17 位有效小数的十进制字符串,然后再转换回双精度,则最终数字必须与原始数字匹配。

另一方面,你不能指望如果你有一个浮点数并以比实际存储的精度更高的精度打印出来,其余的数字将用 0 填充。编译器无法想象您尝试做的技巧。

于 2012-12-07T09:48:24.737 回答