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" 的发展,这些链接非常有趣。