【问题标题】:square root of square of x equals x [duplicate]x的平方根等于x
【发布时间】:2017-03-13 16:13:29
【问题描述】:

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

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

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

这样:

x == z

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

【问题讨论】:

  • x &gt;= 0,对吧?
  • @hvd 是的,对!

标签: floating-point precision numerical-stability


【解决方案1】:

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

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

如果x 不是太大或太小,那么sqrt(y) 将等于x,因为IEEE-754 标准要求+、-、*、/ 和sqrt 适当的圆角。

Examples:

#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;
}

【讨论】:

  • 您能举个例子吗?这也是我的想法,但我无法想出这样的数字。 812387342387487234.98132985798345 == sqrt(812387342387487234.98132985798345^2)
  • @EcirHana 首先想到:一个数字太小以至于它的平方无法表示并产生零。
  • @hvd 是的,无穷大和零是不可恢复的,但其他值呢?请查看编辑。
  • "x 不能从 y 完全恢复" 总是 可以恢复x。粗略:不失一般性,假设0.5 &lt; x &lt; 1.0;显示(假设双精度格式)|y - x^2| &lt;= 2^-54,推导出|sqrt(y) - x| &lt; 2^-54,因此在正确舍入下sqrt(y) 舍入为x。
  • “如果 x 的有效位多于 21 位,则 y 的结果将被截断”不正确。双精度乘法,当它不上溢或下溢时,对于最多 26 个二进制数字的因数是精确的。
【解决方案2】:
#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 的回答的评论在很大程度上是正确的。如果x 和x*x 都是正规范化数字,那么我无法找到x != sqrt(x*x) 的示例,即使使用快速蛮力(在几个小范围内),尽管这不应被视为证明。

【讨论】:

  • 如果x*x不下溢或上溢,则sqrt(x*x) == x的性质在hal.inria.fr/hal-01148409/document中正式证明
  • @PascalCuoq 这很有趣,看起来我有一些阅读要做。 :) OP 没有提到另一个问题确实提到的对非规范化数字的限制,所以它不是完全重复的,但是其他问题加上答案结合确实回答了这个问题,你的答案比我的要好得多。
猜你喜欢
  • 1970-01-01
  • 2021-12-21
  • 2021-09-21
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 2013-03-08
  • 2012-04-02
  • 2014-02-14
相关资源
最近更新 更多