sqrt函数的不同实现效果

首先,感谢参考的博文:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html

由于最神奇的一种方法是我的一个偶像Carmack提出的,所以,就将这几种开方方法调试做了比较,

上代码

/*
*  sqrt 的实现,即开根号
*/

#include <math.h>
#include <time.h>
#include <iostream>
#include <windows.h>

// 方案一  : 二分法
float eps = 1e-7;
float sqrtByBinary(const float n)
{
    if (n < 0)
        return -1;
    float smalls = 0, big = n;
    float mid = (smalls + big) / 2;
    float cur;
    do {
        if (mid*mid > n)
            big = mid;
        else
            smalls = mid;
        cur = mid;
        mid = (smalls + big) / 2;
    } while (abs(mid - cur) > eps);
    return  mid;
}

// 方案二  ; 函数库中的  sqrt 
float sqrtByMath(const float n)
{
    if (n < 0)
        return -1;
    float t = sqrt(n);
    return sqrt(n);
}


// 方案三  牛顿方法递减?
float sqrtByNewton(const float n)
{
    if (n < 0)
        return -1;
    float last,val = n;
    do {
        last = val;
        val = (val + n / val) / 2;
    } while (abs(last - val) > eps);
    return last;
}


//  方案四  卡马克的神奇方法   ----------------------------
float sqrtByQ(float n)
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = n*0.5F;
    y = n;
    i = *(long*)&y;
    i = 0x5f3759df - (i >> 1);
    //  0x5f3759df   //Carmack 的
    //  0x5f37642f   //Lomont  理论推导出的
    //  0x5f375a86   //Lomont  暴力计算出的

    y = *(float*)&i;
    y = y*(threehalfs - (x2*y*y));  //1st iteration
    y = y*(threehalfs - (x2*y*y));  //2st iteration
    return 1/y;
}

using namespace std;
void Test2()
{
    unsigned int loopCount = 10000;

    const int n = 65535;
    time_t t1, t2,t3;
    LARGE_INTEGER d1, d2, d3, d4,d5, d;
    QueryPerformanceFrequency(&d);

    float sqrtN1 = sqrtByBinary(n);
    t1 = time(NULL);
    QueryPerformanceCounter(&d1);
    for(int i = 0; i < loopCount;i++)
        sqrtN1 = sqrtByBinary(n);

    float sqrtN2 = sqrtByMath(n);
    t2 = time(NULL);
    QueryPerformanceCounter(&d2);
    for (int i = 0; i < loopCount; i++)
        sqrtN2 = sqrtByMath(n);
    t3 = time(NULL);
    QueryPerformanceCounter(&d3);

    float sqrtN3 = sqrtByNewton(n);
    for (int i = 0; i < loopCount; i++)
        sqrtN3 = sqrtByNewton(n);
    QueryPerformanceCounter(&d4);

    float sqrtN4 = sqrtByQ(n);
    for (int i = 0; i < loopCount; i++)
        sqrtN4 = sqrtByQ(n);
    QueryPerformanceCounter(&d5);

    printf("      统计sqrt(65536)计算多次的不同方法的时间效率,次数:%d\n", loopCount);
printf("-----------------------------------------------------------------\n");
    printf("%10s%20s%20s\n", "方法", "时间", "计算结果");
    printf("%10s%20.2f%20.8f\n", "二分法", (double)d2.QuadPart - (double)d1.QuadPart, sqrtN1);
    printf("%10s%20.2f%20.8f\n", "系统函数", (double)d3.QuadPart - (double)d2.QuadPart ,sqrtN2);
    printf("%10s%20.2f%20.8f\n", "Newton", (double)d4.QuadPart - (double)d3.QuadPart, sqrtN3);
    printf("%10s%20.2f%20.8f\n", "Carmack", (double)d5.QuadPart - (double)d4.QuadPart, sqrtN4);
    printf("%10s%20.2f%20.8f\n", "Newton(秒)", ((double)d4.QuadPart - (double)d3.QuadPart)/d.QuadPart, sqrtN3);      printf("-----------------------------------------------------------------\n");
}
void main()
{
    Test2();
    system("pause");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值