题目中的问题。
我有一段代码:
double ccss = c * c + s * s;
double sqrtCCSS = sqrt(ccss);
if (sqrtCCSS != 0)
{
n = n1 / sqrtCCSS;
}我只是想知道这是否安全:
double ccss = c * c + s * s;
if (ccss != 0)
{
n = n1 / sqrt(ccss);
}我的直觉告诉我是的,但浮点错误仍然有点神秘。
更新
至少到目前为止,对于Python来说,这似乎是不可能的:
[ins] In [4]: x = np.nextafter(0, 1)
...: print(x)
...: print(np.sqrt(x))
5e-324
2.2227587494850775e-162如果在numpy中最小可能的浮点数(给定的numpy大部分在C中,这似乎是相关的),不能导致零,那么唯一可能导致零的数字必须是引入严重浮点错误但不是最小浮点数的东西。
更新:我更改了变量以满足注释
发布于 2022-10-07 17:47:07
我只是想知道这是否安全: 双xxyy =x*x+y* y;if (xxyy != 0) {n= n1 / sqrt(xxyy);}
这是始终安全的,因为浮点数学不会捕获,而且您可以自由地除以零,甚至Inf/NaN,除非您告诉编译器捕获这些情况。
不管怎么说,如果你只想检查分母是否为零,那么标题上的问题实际上与你在问题的内容中所说的不一样。问题的答案
给定x>0,
sqrt(x)有可能为零吗?
是的,如果正态为零(DAZ)和/或刷新到零(FTZ)被打开。事实上,大多数非x86体系结构都默认启用了DAZ/FTZ,或者甚至不支持取消规范,并且总是打开DAZ/FTZ,因为对非正态数的操作非常慢(参见为什么将0.1f改为0会使性能降低10倍?)。在x86中,您也可以打开这些标志,一些编译器默认会打开这些标志。
例如,下面的示例代码
f = 0x0Cp-1022;
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
printf("%a %a\n", f, sqrt(f));可以打印0x0.000000000000cp-1022 0x0p+0,因为由于DAZ,f被sqrt视为零。
上面的代码段还可以打印0x0p+0 0x0p+0,因为f由于FTZ而被printf视为零,即使它包含一个非零的非规范化值。
如果您在像这样分配f之前设置了DAZ/FTZ
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
f = 0x0Cp-1022;
printf("%a %a\n", f, sqrt(f));然后它可能也会打印0x0p+0 0x0p+0,但是在这种情况下,可以为f分配一个实际的零值,并且打印它的位模式将导致所有的零位
但是如果你问过这个
如果x和y不是同时都为零,那么
sqrt(x*x + y*y)是否可能为零?
那么,这个问题的答案是肯定的,即使没有启用DAZ/FTZ,因为这些数字可能太小,导致产品的流量不足。试着像这样看看
double x = 0x1p-1021;
double y = 0x2p-1020; // or y = 0
double xxyy = x * x + y * y;
printf("%a %a\n", x, y);
printf("%a %a\n", xxyy, sqrt(xxyy));https://stackoverflow.com/questions/73988574
复制相似问题