C,使用 sqrt 和 math.h 时出现编译问题
C, having compile issues when using sqrt and math.h
对于 class 我需要提交一个文件,其中我使用了 math.h 的 sqrt 方法。出于某种原因,除非我使用 -lm 标志将程序 link 到我的文件,否则它无法正确编译。 class 将在不使用 -lm 标志的情况下编译我的代码,所以我想知道是否可以在不使用 -lm 标志的情况下完成这项工作。
谢谢
math.h header 声明在使用 -lm link 编辑的库中实现的函数。如果您不能使用 -lm link,那么您就不能使用 math.h 中的函数。所以,正如@StoryTeller 评论的那样:
Don't use functions from math.h
前段时间我遇到了同样的问题,对那些链接器标志进行了多次尝试,其中更改了 lib 的顺序(none 这些尝试有效)。所以我只是实现了牛顿平方根法。 Link: Square root of a number
用牛顿法做立方根或更高阶根计算函数并不难。:)
这是简单的原型:
double sqaure_root_of(double value){
double s1 = 0;
double q1 = 0;
uint8_t cnt = 0;
uint8_t digit_num = 0;
uint32_t value1 = (uint32_t)value;
while(value1 != 0){
value1 = value1/10;
digit_num++;
}
if((value > 0)&&(value < 1)){
digit_num = 10;
}
if(value <= 0)
return 0;
s1 = value/2;
printf("s1: %f\r\n",s1);
while(cnt < digit_num*2){
q1 = s1*s1;
q1 = q1-value;
q1 = q1/(2*s1);
q1 = s1-q1;
cnt++;
s1 = q1;
}
return q1;
}
有几种方法可以使用 math.h
求一个数的平方根。有迭代方法,例如 Newton 方法(及其所有变体,例如 Newton-Raphson 等)、泰勒级数近似等。但是有一些非常快速、非常准确的特定实现可以找到可用的平方根(或平方根倒数)。
一个这样的实现是 Fast Inverse Square Root 归因于 John Carmack(有一些争议)。虽然它以原始形式找到平方根的倒数,但取倒数来找到平方根是微不足道的。
这里有两个函数(一个用于 float
,一个用于 double
),您可以在没有 math.h
的情况下实现。令人惊奇的是,通过使用特定的 浮点数 常量,您可以在通常会在 3-5 次迭代中收敛的函数中获得令人印象深刻的精度。试试看:
/** John Carmack's, Fast Inverse Square Root (square-root version).
* generally converges within 3 iterations
* see: https://en.wikipedia.org/wiki/Fast_inverse_square_root
*/
float sqrt_fisr (float x)
{
float tmp, xhalf = 0.5f * x;
size_t n_terms = 10;
union {
float f;
int i;
} u;
u.f = x;
u.i = 0x5f3759df - (u.i >> 1);
u.f *= 1.5f - xhalf * u.f * u.f;
while (n_terms-- && u.f != (tmp = u.f * (1.5f - xhalf * u.f * u.f)))
u.f = tmp;
return 1.0f / u.f;
}
如果需要 double
类型,您可以使用以下内容,但 注意 强制使用 uint64_t
类型的 64 位整数(发现在 stdint.h
),
/** John Carmack's Fast Inverse Square Root (square-root double).
* generally converges within 3 iterations
* see: https://en.wikipedia.org/wiki/Fast_inverse_square_root
*/
double sqrtd_fisr (double x)
{
double tmp, xhalf = 0.5d * x;
size_t n_terms = 10;
union {
double d;
uint64_t i;
} u;
u.d = x;
u.i = 0x5fe6eb50c7b537a9 - (u.i >> 1);
u.d *= 1.5d - xhalf * u.d * u.d;
while (n_terms-- && u.d != (tmp = u.d * (1.5d - xhalf * u.d * u.d)))
u.d = tmp;
return 1.0d / u.d;
}
注意:union
上方的 用于允许以整数形式输入 "floating-point constant" 和提供了一种简单的方法来将相同的位(在 float
的情况下为 32,在 double
的情况下为 64
)作为整数或浮点表示形式未使用可能 运行 违反 严格别名规则 .
的内存中的值
维基百科页面中有一些链接讨论了计算中使用的 "magic numbers" 的发展,这些链接非常有趣。
对于 class 我需要提交一个文件,其中我使用了 math.h 的 sqrt 方法。出于某种原因,除非我使用 -lm 标志将程序 link 到我的文件,否则它无法正确编译。 class 将在不使用 -lm 标志的情况下编译我的代码,所以我想知道是否可以在不使用 -lm 标志的情况下完成这项工作。
谢谢
math.h header 声明在使用 -lm link 编辑的库中实现的函数。如果您不能使用 -lm link,那么您就不能使用 math.h 中的函数。所以,正如@StoryTeller 评论的那样:
Don't use functions from
math.h
前段时间我遇到了同样的问题,对那些链接器标志进行了多次尝试,其中更改了 lib 的顺序(none 这些尝试有效)。所以我只是实现了牛顿平方根法。 Link: Square root of a number
用牛顿法做立方根或更高阶根计算函数并不难。:)
这是简单的原型:
double sqaure_root_of(double value){
double s1 = 0;
double q1 = 0;
uint8_t cnt = 0;
uint8_t digit_num = 0;
uint32_t value1 = (uint32_t)value;
while(value1 != 0){
value1 = value1/10;
digit_num++;
}
if((value > 0)&&(value < 1)){
digit_num = 10;
}
if(value <= 0)
return 0;
s1 = value/2;
printf("s1: %f\r\n",s1);
while(cnt < digit_num*2){
q1 = s1*s1;
q1 = q1-value;
q1 = q1/(2*s1);
q1 = s1-q1;
cnt++;
s1 = q1;
}
return q1;
}
有几种方法可以使用 math.h
求一个数的平方根。有迭代方法,例如 Newton 方法(及其所有变体,例如 Newton-Raphson 等)、泰勒级数近似等。但是有一些非常快速、非常准确的特定实现可以找到可用的平方根(或平方根倒数)。
一个这样的实现是 Fast Inverse Square Root 归因于 John Carmack(有一些争议)。虽然它以原始形式找到平方根的倒数,但取倒数来找到平方根是微不足道的。
这里有两个函数(一个用于 float
,一个用于 double
),您可以在没有 math.h
的情况下实现。令人惊奇的是,通过使用特定的 浮点数 常量,您可以在通常会在 3-5 次迭代中收敛的函数中获得令人印象深刻的精度。试试看:
/** John Carmack's, Fast Inverse Square Root (square-root version).
* generally converges within 3 iterations
* see: https://en.wikipedia.org/wiki/Fast_inverse_square_root
*/
float sqrt_fisr (float x)
{
float tmp, xhalf = 0.5f * x;
size_t n_terms = 10;
union {
float f;
int i;
} u;
u.f = x;
u.i = 0x5f3759df - (u.i >> 1);
u.f *= 1.5f - xhalf * u.f * u.f;
while (n_terms-- && u.f != (tmp = u.f * (1.5f - xhalf * u.f * u.f)))
u.f = tmp;
return 1.0f / u.f;
}
如果需要 double
类型,您可以使用以下内容,但 注意 强制使用 uint64_t
类型的 64 位整数(发现在 stdint.h
),
/** John Carmack's Fast Inverse Square Root (square-root double).
* generally converges within 3 iterations
* see: https://en.wikipedia.org/wiki/Fast_inverse_square_root
*/
double sqrtd_fisr (double x)
{
double tmp, xhalf = 0.5d * x;
size_t n_terms = 10;
union {
double d;
uint64_t i;
} u;
u.d = x;
u.i = 0x5fe6eb50c7b537a9 - (u.i >> 1);
u.d *= 1.5d - xhalf * u.d * u.d;
while (n_terms-- && u.d != (tmp = u.d * (1.5d - xhalf * u.d * u.d)))
u.d = tmp;
return 1.0d / u.d;
}
注意:union
上方的 用于允许以整数形式输入 "floating-point constant" 和提供了一种简单的方法来将相同的位(在 float
的情况下为 32,在 double
的情况下为 64
)作为整数或浮点表示形式未使用可能 运行 违反 严格别名规则 .
维基百科页面中有一些链接讨论了计算中使用的 "magic numbers" 的发展,这些链接非常有趣。