免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 10483 | 回复: 2
打印 上一主题 下一主题

[算法] 发个对整数开根号的算法 [复制链接]

论坛徽章:
1
荣誉会员
日期:2011-11-23 16:44:17
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-11-29 11:58 |只看该作者 |倒序浏览
  1. uint8_t ary[256] = {
  2.   0, 16, 16, 16, 32, 32, 32, 32, 32, 48, 48, 48, 48, 48, 48, 48, 64, 64, 68, 68, 72, 72, 76, 76, 76, 80, 80, 84, 84, 84, 88, 88,
  3. 88, 92, 92, 92, 96, 96, 96,100,100,100,104,104,104,108,108,108,108,112,112,112,116,116,116,116,120,120,120,120,124,124,124,124,
  4. 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,143,144,145,146,147,148,149,150,150,151,152,153,154,155,155,156,
  5. 157,158,159,159,160,161,162,163,163,164,165,166,167,167,168,169,170,170,171,172,173,173,174,175,175,176,177,178,178,179,180,181,
  6. 181,182,183,183,184,185,185,186,187,187,188,189,189,190,191,191,192,193,193,194,195,195,196,197,197,198,199,199,200,201,201,202,
  7. 203,203,204,204,205,206,206,207,207,208,209,209,210,211,211,212,212,213,214,214,215,215,216,217,217,218,218,219,219,220,221,221,
  8. 222,222,223,223,224,225,225,226,226,227,227,228,229,229,230,230,231,231,232,232,233,234,234,235,235,236,236,237,237,238,238,239,
  9. 239,240,241,241,242,242,243,243,244,244,245,245,246,246,247,247,248,248,249,249,250,250,251,251,252,252,253,253,254,254,255,255
  10. };  
  11. unsigned int my_sqrt(unsigned int a)
  12. {
  13.     unsigned int b;

  14.     if (a < 256) return (ary[a]) >> 4;
  15.     else if (a < (1 << 12)) b = ary[a >> 4] >> 2;
  16.     else if (a < (1 << 14)) b = ary[a >> 6] >> 1;
  17.     else if (a < (1 << 16)) b = ary[a >> 8]   ;
  18.     else if (a > 4294836225u) return 65535;
  19.     else
  20.     {
  21.         int s = (31 - __builtin_clz((a >> 16)|1)) >> 1;
  22.         unsigned int c = a >> (s + 2);
  23.         b = ary[c >> (s + 8)]; // b=sqrt(c >> s)
  24.         b = c/b + (b << s); //插值 c/b约=b<<s
  25.     }
  26.     return b - (a < b * b);
  27. }
复制代码
这个数组可以这样得到:
  1. int main()
  2. {
  3.     uint8_t ary[256];
  4.     int i = 0, j;
  5.     memset(ary, 0, sizeof(ary));
  6.     for(i = 0; i < 1 << 8; i++) ary[i] = 16*((int)sqrt(i));
  7.     for(; i < 1 << 12; i++) ary[i/16] = 4*((int)sqrt(i));
  8.     for(; i < 1 << 14; i++) ary[i/64] = 2*((int)sqrt(i));
  9.     for(; i < 1 << 16; i++) ary[i/256] = (int)sqrt(i);
  10.     for(i = 0; i < 255; i++)
  11.     {
  12.         printf("%3d,", ary[i]);
  13.         if(i % 32 == 31)
  14.             printf("\n");
  15.     }
  16.     printf("%3d\n", ary[i]);
  17. }
复制代码

评分

参与人数 1可用积分 +6 收起 理由
JohnBull + 6 实用!

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2012-11-29 14:02 |只看该作者
很好,用了,谢谢。

论坛徽章:
3
15-16赛季CBA联赛之山东
日期:2016-10-30 08:47:3015-16赛季CBA联赛之佛山
日期:2016-12-17 00:06:31CU十四周年纪念徽章
日期:2017-12-03 01:04:02
3 [报告]
发表于 2012-11-29 18:06 |只看该作者

好的, 先mark
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP