C算法中的平方根问题
我有一段代码,可以在单位球面上找到一个点。回想一下,对于单位球体: 1=sqrt(x^2+y^2+z^2)C算法中的平方根问题,c,algorithm,sqrt,ieee,C,Algorithm,Sqrt,Ieee,我有一段代码,可以在单位球面上找到一个点。回想一下,对于单位球体: 1=sqrt(x^2+y^2+z^2) 该算法在0和1之间选择两个随机点(x和y坐标)。如果它们的大小小于一,我们就有空间通过求解上面的z方程来定义第三个坐标 void pointOnSphere(double *point){ double x, y; do { x = 2*randf() - 1; y = 2*randf() - 1; } while (x*x + y*y > 1); double
该算法在0和1之间选择两个随机点(x和y坐标)。如果它们的大小小于一,我们就有空间通过求解上面的z方程来定义第三个坐标
void pointOnSphere(double *point){
double x, y;
do {
x = 2*randf() - 1;
y = 2*randf() - 1;
} while (x*x + y*y > 1);
double mag = sqrt(fabs(1 - x*x - y*y));
point[0] = 2*(x*mag);
point[1] = 2*(y*mag);
point[2] = 1 - 2*(mag*mag);
}
从技术上讲,我继承了这段代码。以前的所有者使用“无视严格的标准遵从性”的Ofast进行编译。TL;这意味着您的代码不需要遵循严格的IEEE标准。因此,当我试图在没有优化的情况下编译时,我遇到了一个错误
undefined reference to `sqrt'
什么是IEEE标准?嗯,因为计算机无法将浮点数存储到无限精度,如果不小心,在某些计算过程中会出现舍入错误
在一些谷歌搜索之后,我遇到了一个让我在使用正确的IEEE材料方面走上正轨的问题。我甚至读过关于浮点数的书(我推荐)。不幸的是,它没有回答我的问题
我希望在函数中使用sqrt(),而不是类似的东西。我理解我的算法中的问题可能来自这样一个事实:我可能(尽管不是真的)将一个负数传递给sqrt()函数。我只是不太确定如何解决这个问题。谢谢你的帮助
如果相关的话,我用的是数字发生器
为了澄清,我将libm与-lm链接起来!我还确认它指向了正确的库。至于对
sqrt
的未定义引用,您需要链接到libm
,通常使用-lm
或类似选项
还要注意
如果它们的大小小于一,我们就有空间通过求解上面的z方程来定义第三个坐标
void pointOnSphere(double *point){
double x, y;
do {
x = 2*randf() - 1;
y = 2*randf() - 1;
} while (x*x + y*y > 1);
double mag = sqrt(fabs(1 - x*x - y*y));
point[0] = 2*(x*mag);
point[1] = 2*(y*mag);
point[2] = 1 - 2*(mag*mag);
}
这是错误的。x和y必须满足x*x+y*y为确保点满足条件,测试条件本身,作为
循环的一部分,而不是条件的派生
// functions like `sqrt(), hypot()` benefit with declaration before use
// and without it may generate "undefined reference to `sqrt'"
// Some functions like `sqrt()` are understood and optimized out by a smart compiler.
// Still, best to always declare them.
#include <math.h>
void pointOnSphere(double *point){
double x, y, z;
do {
x = 2*randf() - 1;
y = 2*randf() - 1;
double zz = 1.0 - hypot(x,y);
if (zz < 0.) continue; // On rare negative values due to imprecision
z = sqrt(zz);
if (rand()%2) z = -z; // Flip z half the time
} while (x*x + y*y + z*z > 1); // Must meet this condition
point[0] = x;
point[1] = y;
point[2] = z;
}
//像`sqrt()、hypot()`这样的函数在使用前通过声明受益
//如果没有它,可能会生成“对`sqrt'的未定义引用”
//智能编译器可以理解并优化某些函数,如'sqrt()'。
//不过,最好还是经常申报。
#包括
空心点球体(双*点){
双x,y,z;
做{
x=2*randf()-1;
y=2*randf()-1;
双zz=1.0-低气压(x,y);
if(zz<0.)continue;//由于不精确而导致的罕见负值
z=sqrt(zz);
如果(rand()%2)z=-z;//将z翻转一半时间
}while(x*x+y*y+z*z>1);//必须满足此条件
点[0]=x;
点[1]=y;
点[2]=z;
}
我会用
-Ofast
可能内联了sqrt
调用。使用-lm编译(特别是链接),你应该从你链接的问题中受益,这没有帮助吗?确保代码首先使用#include
“算法选择0和1之间的两个随机点(x和y坐标)。x=2*randf()-1代码>不一致x
在[-10]
之间也可以有负值。您可能认为您正在链接libm,但它很清楚地告诉您您没有。听你的编译器。有时有一个问题是,-lm
必须在gcc
命令中排在最后。另外,可能编译器和/或库没有正确安装?这里所有的其他东西都是分心。找到图书馆!“x和y必须满足x*x+y*y@chux,也许吧。我会说,代码与文本不一致。或者文本非常模糊。我在解决问题的过程中很早就勾选了这个框。我已经链接了libm。这不是问题所在。你对数学的理解是正确的。然后你过早地勾选了这个框。其他一切都是错误的。”分散注意力——让编译器命令指向正确的库。是我自己还是这是唯一一个真正试图回答这个问题的答案?注意:使用球坐标确实会在球体上生成不同于OPs原始方法的点分布:可能更好,也可能更差。但最终计算的|x,y,z|代码>仍然可能超过1.0一点点。如果这是OP的一个问题,一个在过大幅度上重新生成的循环将很容易解决这个问题。