给定一个双精度浮点(非负)数x
,其平方的平方根是否总是等于它自己?
换句话说,如果执行以下操作,是否会降低精度:
x = <non-negative double>
y = x^2
z = sqrt(y)
以便:
x == z
我对平方变为无穷大或零的情况不感兴趣,只是适合双精度的数字。
给定一个双精度浮点(非负)数x
,其平方的平方根是否总是等于它自己?
换句话说,如果执行以下操作,是否会降低精度:
x = <non-negative double>
y = x^2
z = sqrt(y)
以便:
x == z
我对平方变为无穷大或零的情况不感兴趣,只是适合双精度的数字。
对一个数字进行平方,产生一个两倍于原始值位数的值。因此,如果 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;
}
#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)
,尽管这不应被视为证据。