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

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(使用前将#替换为@)

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

  • 左操作数为负数时未定义的行为

    几天前 我在那里参加了微软 GD 实习在线考试 我一直在研究负数左移是一种未定义的行为 但该论文的 30 个问题中几乎有 7 个问题与移位运算符相关 其中大约 5 个问题涉及将负数向左移动 而且他们没有选择说 未定义 行为 看到这一幕我很震
  • 位移位编译器错误还是特殊情况?

    以下代码输出 0 1 32 33 至少可以说这是违反直觉的 但是 如果我用类型注释常量 ONE 替换文字 1 则循环运行正常 这是使用 gcc 4 6 2 和 std c 0x 的情况 include
  • C++ 中 100 位数字的平方根

    无符号长长 最多可以解出15位数字 有没有办法求a的平方根100位数字 你也可以使用Boost 多精度图书馆 该库为一些流行的多精度实现提供了包装器 include
  • Java 将 long 转换为字节 - 哪种方法更有效

    我有两种方法将 long 转换为字节数组 for int i 0 i lt 7 i data pos i byte value gt gt 7 i 1 lt lt 3 and for int i 7 i gt 0 i data p i by
  • Go 语言中的 >> 是什么意思?

    我正在寻找有关 Google Go 语言的信息 在 A Tour of Go 中 他们有这样的代码 const Big 1 lt lt 100 Small Big gt gt 99 但做什么 lt lt and gt gt mean 您可以
  • 在 C# 中,BitArray 获取位值是否比简单的按位移位结合更快?

    1 var bitValue byteValue 1 lt lt bitNumber 0 2 使用System Collections BitArray https learn microsoft com en us dotnet api
  • 计算任意大整数的整数平方根 (isqrt) 的有效算法

    Notice 对于解决方案Erlang or C C go to Trial 4 below 维基百科文章 整数平方根 http en wikipedia org wiki Integer square root 整数平方根 的定义可以在这
  • constexpr 计算负位移位时未定义的行为?

    考虑以下代码片段 int main constexpr int x 1 if x gt 0 constexpr int y 1 lt
  • 使用 Int64 进行位移位

    Int64 变量需要移位 我正在从数据库文件解析伪数学函数 变量是 uint32 或 int32 所以我确实将它们放入 Int64 中以平等地处理它们 而不会丢失任何内容 在我的一个树节点中 我需要对 Int64 进行位移位 不幸的是 移位
  • uint64_t 与 int64_t 的 sqrt

    我注意到计算平方根的整数部分uint64 t比的复杂得多int64 t 请问有人对此有解释吗 为什么处理多一点似乎要困难得多 下列 int64 t sqrt int int64 t a return sqrt a 使用 clang 5 0
  • C 中的移位运算符(<<、>>)是算术运算符还是逻辑运算符?

    在 C 语言中 移位运算符 lt lt gt gt 算术还是逻辑 左移时 算术移位和逻辑移位没有区别 右移时 移位类型取决于被移位的值的类型 作为那些不熟悉差异的读者的背景知识 逻辑 右移 1 位会将所有位向右移动 并用 0 填充最左边的位
  • 二分查找计算平方根 (Java)

    我需要帮助编写一个程序 该程序使用二分搜索递归计算输入非负整数的平方根 向下舍入到最接近的整数 这是我到目前为止所拥有的 import java util Scanner public class Sqrt public static vo
  • 用按位运算替换最低有效位

    用提供的位替换字节的最低有效位的最佳方法是什么 我知道如何检查和比较最后一位 例如使用 posix ffs 函数 但我想知道是否有性能更好的解决方案 而不检查替换位是 0 还是 1 该示例是用 python 伪代码编写的 但我将用 C 实现
  • Java中无符号右移'>>>'运算符[重复]

    这个问题在这里已经有答案了 可能的重复 为什么 1 gt gt gt 32 1 https stackoverflow com questions 4813909 why is 1 32 1 无符号右移运算符在最左边插入 0 所以当我这样做
  • Clojure:跨列表的复杂迭代?

    我想要一个数字 20 和一个清单 1 2 3 4 5 6 7 8 9 10 并返回一个集合 其中原始列表中的每个值包含两个值 原始值与该值除 20 时的余数配对 如果原始值以某种方式与余数相关 那就太好了 这样我就可以轻松检索产生特定余数的
  • Java位移位的奇怪之处

    Java 有 2 个用于右移的位移运算符 gt gt shifts right and is dependant on the sign bit for the sign of the result gt gt gt shifts righ
  • 在C++中,1和1i64有什么区别?

    我正在将一些 32 位兼容代码转换为 64 位 但我遇到了障碍 我正在编译 VS2008 x64 项目 并且收到以下警告 warning C4334 lt lt result of 32 bit shift implicitly conve
  • 什么时候右移操作>>移位符号位什么时候不呢?

    我的问题是为什么a gt gt 1移位符号位 但不移位 a 0xaaaaaaaa gt gt 1 代码片段 int a 0xaaaaaaaa std cout lt lt sizeof a lt lt std endl getBits a
  • 左移 255 位(作为一个字节)

    谁能解释为什么以下内容无法编译 byte b 255 lt lt 1 错误 常量值 510 无法转换为 字节 我期待二进制的以下内容 1111 1110 类型转换难倒了我 C 中的数字文字是int not byte 编译器将评估位移位 因此
  • 在 Rust 中,太大的位移是否是未定义的行为?

    当您运行此代码时 allow exceeding bitshifts fn main const NUMBER u64 0b 10101010 fn print shift i u32 println b NUMBER gt gt i pr

随机推荐