使用位移位求整数平方根的最快方法是什么?

2024-01-11

我一直在寻找最快的方法来计算数字(整数)的平方根(整数)。我在维基百科中遇到了这个解决方案,它找到一个数字的平方根(如果它是一个完美的平方)或其最接近的下完美平方的平方根(如果给定的数字不是一个完美的平方:

short isqrt(short num) {
    short res = 0;
    short bit = 1 << 14; // The second-to-top bit is set: 1L<<30 for long
    // "bit" starts at the highest power of four <= the argument.
    while (bit > num)
        bit >>= 2;
    while (bit != 0) {
        if (num >= res + bit) {
            num -= res + bit;
            res = (res >> 1) + bit;
        }
        else
            res >>= 1;
        bit >>= 2;
    }
    return res;
}

我尝试了很多测试运行来跟踪算法,但我似乎不理解里面的部分while(bit!=0)。有人可以向我解释这部分吗?


我也找出了一些小例子,我想我明白了。据我了解,该算法从最高位到最低位一次构建一个二进制数字的答案。

令“num_init”为函数开头处的 num 值。假设在某个迭代中,我们有 bit = 4^x 并且 num 等于某个值“num_curr”(快速浏览一下,直到 bit 为 0,它始终是 4 的幂)。那么 res 的形式为 y*2^(x+1),其中 y^2 + num_curr = num_init,并且 y 小于实际答案,但在 2^x 之内。

num、res 和 bit 值的不变性将是关键。在代码中完成此操作的方式是

while (bit != 0) {
    ....
}

正在将我们的假想指针从左向右移动,并且在每一步中我们确定该位是 0 还是 1。

转到第一个 if 语句,假设我们的假想“构建”整数等于 y,并且我们正在查看 2^x 位。那么,当且仅当 num 的原始值至少为 (y + 2^x)^2 = y^2 + y*2^(x+1) + 4^x 时,该位为 1。换句话说,如果 num 在该点的值至少为 y*2^(x+1) + 4^x(因为我们有 num 的值下降了 y^2 的不变量),则该位为 1 。很方便,res = y*2^(x+1) 且 bit = 4^x。然后我们就明白了背后的要点

if (num >= res + bit) {
    num -= res + bit;
    res = (res >> 1) + bit;
}
else 
    res >>= 1;   

如有必要,它会在我们的假想位置添加 1 位,然后更新 res 和 num 以保持不变。最后

bit >>= 2;

更新位并将所有内容向前移动一步。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用位移位求整数平方根的最快方法是什么? 的相关文章

  • C++ 中 100 位数字的平方根

    无符号长长 最多可以解出15位数字 有没有办法求a的平方根100位数字 你也可以使用Boost 多精度图书馆 该库为一些流行的多精度实现提供了包装器 include
  • 使用 MIPS 汇编中的逻辑移位乘以 2 的幂

    有人可以指导我如何在 MIPS 汇编中使用移位来制作乘法代码吗 我不明白数字 2 n 如何帮助我使用奇数被乘数进行乘法 我目前有这段代码 我正在尝试制作一个计算器 text li v0 4 la a0 ask 1 syscall li v0
  • 位移位大型二进制文件?

    在 C 中对大量二进制数据进行位移位的最佳或推荐方法是什么 我有一个 200K 二进制文件 我想左移然后右移整个文件 如果您的操作系统可以支持它 请使用内存映射文件 然后做一点移位就会非常非常高效 请参阅此答案以获取更多信息 内存映射文件有
  • 在 C 中操作 80 位数据类型

    我正在用 C 实现一些加密算法 其中涉及 80 位密钥 特定操作涉及将密钥旋转移位 x 个位数 我已经尝试过 long double 类型 如果我没记错的话 它是 80 位 但这不适用于位移运算符 我能想到的唯一替代方案是使用 10 个元素
  • 警告:左移计数 >= 类型宽度

    我对处理位非常陌生 并且在编译时遇到以下警告 7 warning left shift count gt width of type 我的7号线是这样的 unsigned long int x 1 lt lt 32 如果大小是有意义的lon
  • 右移和有符号整数

    在我的编译器上 以下伪代码 值替换为二进制 sint32 word 10000000 00000000 00000000 00000000 word gt gt 16 产生一个word位字段如下所示 11111111 11111111 10
  • 在 C 中声明 64 位变量

    我有个问题 uint64 t var 1 this is 000000 00001 right 在我的代码中 这是有效的 var 1 lt lt 43 但它怎么知道 1 应该是 64 位的呢 我不应该写这个吗 var uint64 t 1
  • 如何让(1 << 9)通过MISRA? [复制]

    这个问题在这里已经有答案了 我们使用 Parasoft 静态分析并打开 MISRA C 2004 检查器 该软件是一个嵌入式系统 我们喜欢这样描述常量 1 define MOTOR ON 1 lt lt 9 这表明寄存器中的第 9 位应该是
  • 自然对齐的内存地址

    我需要从现有的64位值中提取一个内存地址 这个地址指向一个4K数组 起始值为 0x000000030c486000 我需要的地址存储在位 51 12 中 因此我使用以下方法提取这些位 address start gt gt 12 0x000
  • 为什么我会得到负值位移的奇怪结果?

    这个问题不是重复的这个问题 https stackoverflow com questions 1857928 right shifting negative numbers in c 我遇到过一种情况 我可能必须将 正 数字左移负值 即
  • 什么是 JavaScript >>> 运算符以及如何使用它?

    我正在查看 Mozilla 中向 Array 添加过滤方法的代码 其中有一行代码让我感到困惑 var len this length gt gt gt 0 我以前从未见过在 JavaScript 中使用 gt gt gt 它是什么以及它有什
  • Java中无符号右移'>>>'运算符[重复]

    这个问题在这里已经有答案了 可能的重复 为什么 1 gt gt gt 32 1 https stackoverflow com questions 4813909 why is 1 32 1 无符号右移运算符在最左边插入 0 所以当我这样做
  • 在Python中旋转位

    出于好奇 我想看看将对象的 id 转换为其哈希值的操作在字符串域中是什么样子 而不是使用通常的按位操作 例如 class A pass def my hash a bits format id a 064b rot4 bits 4 bits
  • c/c++ 左移无符号 vs 有符号

    我有这个代码 include
  • 在 C 中,通过常量进行位移与通过具有相同值的变量进行位移之间有区别吗?

    我正在尝试对值进行位移0xFFFFFFFF32 位 它正确地得出 0 如果我写 x x lt lt 32 但它仍然是0xFFFFFFFF 当我写 x x lt lt y when y 32 我真的完全不明白这一点 不过 对于移动的函数 我需
  • 在C++中,1和1i64有什么区别?

    我正在将一些 32 位兼容代码转换为 64 位 但我遇到了障碍 我正在编译 VS2008 x64 项目 并且收到以下警告 warning C4334 lt lt result of 32 bit shift implicitly conve
  • 仅使用整数求平方根

    最近 我在某人的编程课上遇到了一个问题 它要求他们仅使用整数来计算平方根 他们用一个整数来表示小数点之前的部分 用另一个整数来表示小数点之后的部分 问题说不允许使用浮点数 然而 经过一段时间的思考 我似乎无法想出一种不使用浮点的方法 我用谷
  • 为什么 Python 布尔值占用超过一个字节?

    显然 Python 中整数占用 24 个字节 我可以理解 它这样做是因为代表无限数字的额外花哨 然而 布尔数据类型看起来也花费了高达 24 个字节 尽管它只能表示两个可能值之一 为什么 除了 1 位表示之外 还可能需要存储哪些额外数据Tru
  • 对无符号 8 位整数进行左移操作 [重复]

    这个问题在这里已经有答案了 我试图理解 C C 中的移位运算符 但它们给我带来了困难 我有一个无符号 8 位整数 初始化为一个值 例如 1 uint8 t x 1 根据我的理解 它在内存中的表示方式如下 0 0 0 0 0 0 0 1 现在
  • 为什么 -1 >> 1 和 0xFFFFFFFF >> 1 会产生不同的结果?

    我正在尝试做一个测试来判断我的电脑是否通过右移十六进制执行算术右移或逻辑右移FFFFFFFF by 1 我知道一个整数 1读作FFFFFFFF十六进制 因为它是二进制补码1 右移 1 by 1结果是FFFFFFFF并显示 PC 执行算术右移

随机推荐