【问题标题】:Predefined squareroot function without using sqrt() from math.h in C [closed]在 C 中不使用 math.h 中的 sqrt() 的预定义平方根函数 [关闭]
【发布时间】:2009-01-25 00:39:16
【问题描述】:

家庭作业问题:

  • Cygwin GNU GDB
  • Cygwin GNU GCC

尝试根据 2 的 A 次方和 B 2 次方的平方根来确定 斜边 C 的长度。

示例输入:

输入直角三角形两条边的长度:2.25 8.33

答案:

斜边的长度为:8.628523

  • 问题:当我指定与上面相同的输入时,结果不是 same - 输出是 19.84.9596

完整的代码如下:

float squareRoots(float *s)
{
    float cx;
    float nx;
    float e;

    cx = 1;
    nx = (cx +*s/cx)/2;
    e = nx - cx;
    cx = nx;

    if (e*e > 0.001)
    {
        nx = (cx +*s/cx)/2;
        return nx;
    } else {
        return nx;
    }
}

float hypotenuse(float *a, float *b)
{
    float c;
    //raise a to power of 2
    *a = (*a * *a);
    *b = (*b * *b);
    //add a and b
    float y = *a + *b;
    c = squareRoots(&y);

    return c;
}


int main()
{
    float x,y;

    printf("Enter the length of two sides of a right-angled triangle:");
    scanf("%f %f", &x, &y);
    float k=hypotenuse(&x,&y);

    printf("The length of the hypotenuse is: %f", k);

    exit(0);
}

【问题讨论】:

  • 你到底为什么将指针传递给浮点数而不是按值传递?
  • @Andrew - 我同意;确实,鉴于代码也在修改值,这非常可怕。

标签: c windows math


【解决方案1】:

您(应该是?)使用的平方根算法称为Newton's method。你的 if 语句应该是一个 while 循环。

替换

if (e*e > 0.001)
{
        nx = (cx +*s/cx)/2;
        return nx;
} else {
        return nx;
}

使用 while 循环迭代地执行相同的操作,但包括重新计算 e。

我会给你工作代码,但你说这是作业。如果你不能让它工作,发布你的新代码,我很乐意帮助你解决问题。

【讨论】:

  • @Bill:它通常被称为“Newton-Raphson”,至少在我见过的大多数裁判中是这样的:)
  • 不敢相信我没有注意到这一点......
  • @Atklin:如果您最近参加了数值方法课程,那么您应该参加。 :)
【解决方案2】:

想要一个超级重复的平方根实现?查看John Carmack's magic square root from Quake III

float Q_rsqrt( float number )
{
  long i;
  float x2, y;
  const float threehalfs = 1.5F;

  x2 = number * 0.5F;
  y  = number;
  i  = * ( long * ) &y;  // evil floating point bit level hacking
  i  = 0x5f3759df - ( i >> 1 ); // what the ****?
  y  = * ( float * ) &i;
  y  = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  // y  = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed

  #ifndef Q3_VM
  #ifdef __linux__
    assert( !isnan(y) ); // bk010122 - FPE?
  #endif
  #endif
  return y;
}

【讨论】:

  • 不幸的是,我必须使用所描述的算法......
  • 请注意,这实际上是逆平方根函数,因此您必须将结果乘以 1/x 才能得到平方根。
  • 在阅读 IEEE 规范并弄清楚如何根据 log2 编写 sqrt 后,“wtf”部分将变得清晰。此外,关于所使用的常量的论文已经写过。
  • 此外,与普遍看法相反,常数不是最初的猜测。 (i >> 1) 部分做了很多。常量唯一要做的就是调整初始猜测。
【解决方案3】:

我的答案是 8.628522469,即 8.628522。

【讨论】:

  • 使用相同的代码?奇怪 - 我正在使用 GNU GDB 在 cygwin 下编译...
  • 不,您没有使用 gdb 进行编译。您可能正在使用 gcc 进行编译。
猜你喜欢
  • 1970-01-01
  • 2013-11-05
  • 1970-01-01
  • 2018-02-21
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-14
相关资源
最近更新 更多