当前位置: 首页 > 知识库问答 >
问题:

了解Integer.highestOneBit()方法实现背后的逻辑

郑嘉年
2023-03-14

Java Integer类具有静态方法highestOneBit方法,该方法将返回一个单个一位的值,该值位于指定值中最高一位的位置,如果指定值本身等于零,则返回零。

例如,int 17的输入将返回16;因为17可以用二进制表示为10001,所以它将返回等于16的最左边的位。

在整数类中,它在Java文档中具有以下实现。

    public static int highestOneBit(int i) {
    // HD, Figure 3-1
    i |= (i >>  1);
    i |= (i >>  2);
    i |= (i >>  4);
    i |= (i >>  8);
    i |= (i >> 16);
    return i - (i >>> 1);
}

我只想知道以这种方式实现它背后的逻辑以及使用 shift 操作背后的逻辑。谁能给它一些启示。

共有3个答案

易昌翰
2023-03-14

前五行(i|=(i

为了简单起见,让我们假设<code>int</code>是8位。在这种情况下,代码如下:

public static int highestOneBit(int i) {
    i |= (i >>  1);
    i |= (i >>  2);
    i |= (i >>  4);
    return i - (i >>> 1);
}

现在,假设我们的值是128(1000000)。这是会发生的情况:

// i == 10000000
i |= (i >>  1); // i = 10000000 | 11000000 = 11000000 
i |= (i >>  2); // i = 11000000 | 11110000 = 11110000 
i |= (i >>  4); // i = 11110000 | 11111111 = 11111111
return i - (i >>> 1); // 11111111 - 01111111 = 10000000

现在,让我们尝试64(01000000):

// i == 01000000
i |= (i >>  1); // i = 01000000 | 00100000 = 01100000 
i |= (i >>  2); // i = 01100000 | 00011000 = 01111000 
i |= (i >>  4); // i = 01111000 | 00000111 = 01111111
return i - (i >>> 1); // 01111111 - 00111111 = 01000000

艾学海
2023-03-14

i|=语句有助于计算与i长度相同的一系列语句。例如,对于101011,它计算111111。我已经解释了它在这个答案中是如何工作的(我现在无法重新键入它,因为我在移动设备上)。

所以基本上,一旦你有了一串1,减法本身右移一位就得到了H.O.位。

111111 - (111111 >>> 1) = 111111 - 011111 = 100000
戚哲
2023-03-14

该算法计算给定的<code>i</code>,其二进制表示为:

0..01XXXXXXX...XXXX

价值

0..011111111...1111

这就是 5 |= 运算符所做的。

然后,在return语句中,它从中减去右移一位的值

0..001111111...1111

得到结果

0..010000000...0000

它是如何工作的:

第32位(最左边)可能的最高1位。假设输入数字的该位为1:

1XXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX

您或该值右移1<code>(i

11XXXXXX XXXXXXXX XXXXXXXX XXXXXXXX

然后,您或值右移2(i)的新值

1111XXXX XXXXXXXX XXXXXXXX XXXXXXXX

然后您或该值右移4的新值(i

11111111 XXXXXXXX XXXXXXXX XXXXXXXX

然后你或那个新值,该值向右移动了 8 (i

11111111 11111111 XXXXXXXX XXXXXXXX

最后,您或该值右移16 <代码>的新值(I

11111111 11111111 11111111 11111111

如果最高的1位小于第32位,则这些操作仍将其右侧的所有位变为1,并将剩余的(较高的位)保持为0。

 类似资料:
  • 根据《联合法律法规》第15.19条: 如果左手操作数的提升类型是长的,那么只使用右手操作数的六个最低阶位作为移位距离。这就好像右边的操作数服从一个位逻辑AND运算符(§15.22.1),掩码值为0x3f(0b111111)。因此,实际使用的移位距离总是在0到63的范围内,包括在内。 我们可以在C#中找到同样的东西。在Python中,它将是6位而不是5位,但逻辑保持不变。 背后的理由是什么?对我来说

  • 我正试图从现实中解决一个问题 “偶数总和” 但是我不能这样做。下面是问题。 即使是总和也是两个玩家的游戏。玩家将获得N个正整数序列并轮流进行。在每个回合中,玩家选择一个非空切片(连续元素的子序列),使得该切片中的值之和是偶数,然后删除切片并连接序列的其余部分。第一个无法做出合法举动的玩家将输掉比赛。 如果你和你的对手玩这场游戏,你想知道你是否能赢,假设你和对手都玩得很好。你先走。 写一个函数:

  • 此方法的任务是从数组中移除要移除的值。剩下的元素应该只向数组的开头移动。(数组的大小不会改变。)由于数组现在少了一个元素,最后一个元素的位置应该用0填充。如果数组中有多个toRemove的匹配项,则只应移除第一个匹配项。方法没有返回值,如果数组没有元素,它应该只是没有效果。 解决方案: 我不明白这个算法是如何工作的。boolean的使用让我感到困惑,我觉得我不完全理解原始数据类型是做什么的,我知道

  • 本文向大家介绍javascript背景时钟实现方法,包括了javascript背景时钟实现方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了javascript背景时钟实现方法。分享给大家供大家参考。具体如下: 以下是这个效果的全部代码。[最好从一个空页面开始] 说明:时钟显示的位置需要你修正TOP,LEFT参数来确定。TOP表示层距离显示器顶部的象素值,LEFT表示距离左侧的象素值。

  • 问题内容: 在Java中,可以使用 AtomicMarkableReference 原子地更新对象引用以及标记位。 该javadoc的状态: 实施注意事项:此实现通过创建表示“装箱的” [reference,boolean]对的内部对象来维护可标记的引用。 根据在该类的Java 8源代码中可以看到的情况,这是正确的: 该类的get方法的设计背后是否有原因? 使用这种布尔数组(而不是返回值对)有什么

  • 问题内容: 我正在使用JWT保护节点js URL https://github.com/auth0/express- jwt 要创建JWT令牌用户会话,我只需执行以下操作: 或在登录电话的情况下 每次调用受保护的URL时,我都会检查JWT中间件是否自动设置了该URL 。 现在我想知道: 1-调用sign()时,JWT令牌存储在哪里? 2-每次调用受保护的网址时,我都必须验证()令牌吗?如果是,为什