为了账号安全,请及时绑定邮箱和手机立即绑定

编写自己的平方根函数

编写自己的平方根函数

您如何编写自己的函数来查找整数的最精确平方根?对其进行谷歌搜索之后,我发现了它(从其原始链接存档),但是首先,我没有完全了解它,其次,它也是近似的。假设平方根是最接近的整数(实际根数)或浮点数。
查看完整描述

3 回答

?
慕村225694

TA贡献1880条经验 获得超4个赞

以下计算N> 0的floor(sqrt(N)):


x = 2^ceil(numbits(N)/2)

loop:

    y = floor((x + floor(N/x))/2)

    if y >= x

        return x

    x = y

这是Crandall&Pomerance的“素数:一种计算视角”中给出的牛顿方法的一种形式。之所以要使用此版本,是因为知道他们在做什么的人都证明了它完全收敛于平方根的底面,而且它很简单,因此实现错误的可能性很小。它也很快(尽管可以构造甚至更快的算法,但是正确地执行则要复杂得多)。对于很小的N,正确实现的二进制搜索可能会更快,但是您也可以在其中使用查找表。


要舍入到最接近的整数,只需使用上述算法计算t = floor(sqrt(4N))。如果设置了t的最低有效位,则选择x =(t + 1)/ 2; 否则选择t / 2。请注意,这四舍五入。您还可以通过查看余数是否为非零(即t ^ 2 == 4N)来舍入(或舍入为偶数)。


请注意,您不需要使用浮点运算。实际上,您不应该这样。该算法应完全使用整数来实现(特别是floor()函数仅指示应使用常规整数除法)。


查看完整回答
反对 回复 2019-10-05
?
大话西游666

TA贡献1817条经验 获得超14个赞

根据您的需求,可以使用简单的分而治之策略。它的收敛速度不会像其他方法那样快,但是对于新手来说可能更容易理解。另外,由于它是O(log n)算法(每次迭代将搜索空间减半),所以32位浮点数的最坏情况是32次迭代。


假设您想要62.104的平方根。您选择一个介于0和那个之间的值,并将其平方。如果平方比您的数字高,则需要专注于小于中点的数字。如果太低,则专注于较高的那些。


使用真实的数学运算,您可以将搜索空间永远永远分成两部分(如果没有合理的平方根)。实际上,计算机最终将失去精度,您将获得近似值。以下C程序说明了这一点:


#include <stdio.h>

#include <stdlib.h>


int main (int argc, char *argv[]) {

    float val, low, high, mid, oldmid, midsqr;

    int step = 0;


    // Get argument, force to non-negative.


    if (argc < 2) {

        printf ("Usage: sqrt <number>\n");

        return 1;

    }

    val = fabs (atof (argv[1]));


    // Set initial bounds and print heading.


    low = 0;

    high = mid = val;

    oldmid = -1;


    printf ("%4s  %10s  %10s  %10s  %10s  %10s    %s\n",

        "Step", "Number", "Low", "High", "Mid", "Square", "Result");


    // Keep going until accurate enough.


    while (fabs(oldmid - mid) >= 0.00001) {

        oldmid = mid;


        // Get midpoint and see if we need lower or higher.


        mid = (high + low) / 2;

        midsqr = mid * mid;

        printf ("%4d  %10.4f  %10.4f  %10.4f  %10.4f  %10.4f  ",

            ++step, val, low, high, mid, midsqr);

        if (mid * mid > val) {

            high = mid;

            printf ("- too high\n");

        } else {

            low = mid;

            printf ("- too low\n");

        }

    }


    // Desired accuracy reached, print it.


    printf ("sqrt(%.4f) = %.4f\n", val, mid);

    return 0;

}

这是几次运行,因此希望您能了解其工作原理。对于77:


pax> sqrt 77

Step      Number         Low        High         Mid      Square    Result

   1     77.0000      0.0000     77.0000     38.5000   1482.2500  - too high

   2     77.0000      0.0000     38.5000     19.2500    370.5625  - too high

   3     77.0000      0.0000     19.2500      9.6250     92.6406  - too high

   4     77.0000      0.0000      9.6250      4.8125     23.1602  - too low

   5     77.0000      4.8125      9.6250      7.2188     52.1104  - too low

   6     77.0000      7.2188      9.6250      8.4219     70.9280  - too low

   7     77.0000      8.4219      9.6250      9.0234     81.4224  - too high

   8     77.0000      8.4219      9.0234      8.7227     76.0847  - too low

   9     77.0000      8.7227      9.0234      8.8730     78.7310  - too high

  10     77.0000      8.7227      8.8730      8.7979     77.4022  - too high

  11     77.0000      8.7227      8.7979      8.7603     76.7421  - too low

  12     77.0000      8.7603      8.7979      8.7791     77.0718  - too high

  13     77.0000      8.7603      8.7791      8.7697     76.9068  - too low

  14     77.0000      8.7697      8.7791      8.7744     76.9893  - too low

  15     77.0000      8.7744      8.7791      8.7767     77.0305  - too high

  16     77.0000      8.7744      8.7767      8.7755     77.0099  - too high

  17     77.0000      8.7744      8.7755      8.7749     76.9996  - too low

  18     77.0000      8.7749      8.7755      8.7752     77.0047  - too high

  19     77.0000      8.7749      8.7752      8.7751     77.0022  - too high

  20     77.0000      8.7749      8.7751      8.7750     77.0009  - too high

  21     77.0000      8.7749      8.7750      8.7750     77.0002  - too high

  22     77.0000      8.7749      8.7750      8.7750     76.9999  - too low

  23     77.0000      8.7750      8.7750      8.7750     77.0000  - too low

sqrt(77.0000) = 8.7750

对于62.104:


pax> sqrt 62.104

Step      Number         Low        High         Mid      Square    Result

   1     62.1040      0.0000     62.1040     31.0520    964.2267  - too high

   2     62.1040      0.0000     31.0520     15.5260    241.0567  - too high

   3     62.1040      0.0000     15.5260      7.7630     60.2642  - too low

   4     62.1040      7.7630     15.5260     11.6445    135.5944  - too high

   5     62.1040      7.7630     11.6445      9.7037     94.1628  - too high

   6     62.1040      7.7630      9.7037      8.7334     76.2718  - too high

   7     62.1040      7.7630      8.7334      8.2482     68.0326  - too high

   8     62.1040      7.7630      8.2482      8.0056     64.0895  - too high

   9     62.1040      7.7630      8.0056      7.8843     62.1621  - too high

  10     62.1040      7.7630      7.8843      7.8236     61.2095  - too low

  11     62.1040      7.8236      7.8843      7.8540     61.6849  - too low

  12     62.1040      7.8540      7.8843      7.8691     61.9233  - too low

  13     62.1040      7.8691      7.8843      7.8767     62.0426  - too low

  14     62.1040      7.8767      7.8843      7.8805     62.1024  - too low

  15     62.1040      7.8805      7.8843      7.8824     62.1323  - too high

  16     62.1040      7.8805      7.8824      7.8815     62.1173  - too high

  17     62.1040      7.8805      7.8815      7.8810     62.1098  - too high

  18     62.1040      7.8805      7.8810      7.8807     62.1061  - too high

  19     62.1040      7.8805      7.8807      7.8806     62.1042  - too high

  20     62.1040      7.8805      7.8806      7.8806     62.1033  - too low

  21     62.1040      7.8806      7.8806      7.8806     62.1038  - too low

  22     62.1040      7.8806      7.8806      7.8806     62.1040  - too high

  23     62.1040      7.8806      7.8806      7.8806     62.1039  - too high

sqrt(62.1040) = 7.8806

对于49:


pax> sqrt 49

Step      Number         Low        High         Mid      Square    Result

   1     49.0000      0.0000     49.0000     24.5000    600.2500  - too high

   2     49.0000      0.0000     24.5000     12.2500    150.0625  - too high

   3     49.0000      0.0000     12.2500      6.1250     37.5156  - too low

   4     49.0000      6.1250     12.2500      9.1875     84.4102  - too high

   5     49.0000      6.1250      9.1875      7.6562     58.6182  - too high

   6     49.0000      6.1250      7.6562      6.8906     47.4807  - too low

   7     49.0000      6.8906      7.6562      7.2734     52.9029  - too high

   8     49.0000      6.8906      7.2734      7.0820     50.1552  - too high

   9     49.0000      6.8906      7.0820      6.9863     48.8088  - too low

  10     49.0000      6.9863      7.0820      7.0342     49.4797  - too high

  11     49.0000      6.9863      7.0342      7.0103     49.1437  - too high

  12     49.0000      6.9863      7.0103      6.9983     48.9761  - too low

  13     49.0000      6.9983      7.0103      7.0043     49.0598  - too high

  14     49.0000      6.9983      7.0043      7.0013     49.0179  - too high

  15     49.0000      6.9983      7.0013      6.9998     48.9970  - too low

  16     49.0000      6.9998      7.0013      7.0005     49.0075  - too high

  17     49.0000      6.9998      7.0005      7.0002     49.0022  - too high

  18     49.0000      6.9998      7.0002      7.0000     48.9996  - too low

  19     49.0000      7.0000      7.0002      7.0001     49.0009  - too high

  20     49.0000      7.0000      7.0001      7.0000     49.0003  - too high

  21     49.0000      7.0000      7.0000      7.0000     49.0000  - too low

  22     49.0000      7.0000      7.0000      7.0000     49.0001  - too high

  23     49.0000      7.0000      7.0000      7.0000     49.0000  - too high

sqrt(49.0000) = 7.0000


查看完整回答
反对 回复 2019-10-05
?
临摹微笑

TA贡献1982条经验 获得超2个赞

一种简单(但不是很快)的方法来计算X的平方根:


squareroot(x)

    if x<0 then Error

    a = 1

    b = x

    while (abs(a-b)>ErrorMargin) 

        a = (a+b)/2

        b = x/a

    endwhile

    return a;

示例:squareroot(70000)


    a       b

    1   70000

35001       2

17502       4

 8753       8

 4381      16

 2199      32

 1116      63

  590     119

  355     197

  276     254

  265     264

如您所见,它定义了平方根的上下边界,并缩小了边界直到其大小可以接受为止。


有许多更有效的方法,但是这一方法说明了该过程并且易于理解。


请注意,如果使用整数,则将Errormargin设置为1,否则会出现无限循环。


查看完整回答
反对 回复 2019-10-05
  • 3 回答
  • 0 关注
  • 1006 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信