1

给定一个双精度浮点(非负)数x,其平方的平方根是否总是等于它自己?

换句话说,如果执行以下操作,是否会降低精度:

x = <non-negative double>
y = x^2
z = sqrt(y)

以便:

x == z

我对平方变为无穷大或零的情况不感兴趣,只是适合双精度的数字。

4

2 回答 2

2

对一个数字进行平方,产生一个两倍于原始值位数的值。因此,如果 x 太大,那么一些位会丢失x^2并且x无法从y[编辑:仍然可以通过适当的舍入从 y 中获得 x] 完全恢复。在 IEEE-754 双精度的情况下,如果x有效数字部分超过 26 位,则结果y将被截断。这是最简单的情况。

如果x有效位很少,但指数非常大或非常小,那么x^2对于双精度来说可能太大了,并且会变成inf非正规数,在这种情况下无法恢复x

如果x不是太大或太小,则等于sqrt(y)x因为 IEEE-754 标准要求+, -,*和正确舍入/sqrt

例子:

#include <iostream>
#include <ios>
#include <iomanip>
#include <cmath>

using std::fixed;
using std::hexfloat;
using std::cout;

int main() {
    double x = 1.25e155;
    double y = x*x;
    cout << hexfloat << "x = " << x << ", y = " << y << ", sqrt(y) = " << sqrt(y) << '\n';
    
    x = 1.25e-155;
    y = x*x;
    cout << hexfloat << "x = " << x << ", y = " << y << ", sqrt(y) = " << sqrt(y) << '\n';
    return 0;
}
于 2017-03-13T16:23:25.540 回答
1
#include <stdio.h>
#include <math.h>

int main(void) {
  double x = 1.0000000000000001E-160;
  double square = x*x;
  double root = sqrt(square);
  if (root != x) {
    printf("%.20g\n", x);
    printf("%.20g\n", root);
  }
}

输出

1.0000000000000001466e-160
9.9999443357584897793e-161

这里发生的情况是,x它足够大,以至于它的平方不为零,但又足够小,以至于它的平方只能表示为非规范化的数字,这会降低可用的精度。

我的印象是@MarkDickinson 对@LưuVĩnhPhúc 的回答的评论在很大程度上是正确的。如果两者xx*x都是正归一化数字,那么即使使用快速蛮力(在几个小范围内),我也无法找到示例x != sqrt(x*x),尽管这不应被视为证据。

于 2017-03-13T18:18:04.900 回答