Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java中的位旋转-将long分解为long[]位掩码_Java_Bit Manipulation - Fatal编程技术网

java中的位旋转-将long分解为long[]位掩码

java中的位旋转-将long分解为long[]位掩码,java,bit-manipulation,Java,Bit Manipulation,我将一个long分解为一个long[]的单位long public static int decompose(long[] buffer, long base) { int count = Long.bitCount(base); for (int i=0; i<count; i++) { base ^= (buffer[i] = Long.lowestOneBit(base)); } return count; } 公共静态int分解(长[]缓冲区,长基){ i

我将一个long分解为一个long[]的单位long

public static int decompose(long[] buffer, long base) {
  int count = Long.bitCount(base);
  for (int i=0; i<count; i++) {
    base ^= (buffer[i] = Long.lowestOneBit(base));
  }
  return count;
}
公共静态int分解(长[]缓冲区,长基){
int count=Long.bitCount(基);

对于(int i=0;i因为我喜欢优化*,这里有一个版本你可以试试:

public static int decompose(long[] buffer, long base) {
    int count = 0;
    while (base != 0) {
        long mask = base & (-base);
        base &= ~mask;
        buffer[count++] = mask;
    }
    return count;
}
我做的主要事情是:

  • 内联最小的一位计算,以避免方法调用开销。在编译器/JVM不够聪明的情况下,这可能是一个胜利,因为编译器/JVM不能为您完成这项工作
  • 将long数组作为输入参数传递,以避免内存分配和计算位以确定数组大小的需要。函数现在返回找到的位掩码数
  • 在进行时将位归零,以便尽早从循环中退出

*因为它很有趣,无论它是否过早

我都会使用一个掩码,在每个循环中使用shift操作符计算:

for (int i= 0; i < result.length; i++)
    result[i]= base & (1<<i);
for(int i=0;i结果[i]=base&(1这是我目前正在使用的工具。我一直认为问题中的代码(方法1)的执行速度要快得多。目前,马克·彼得斯的答案通常是最快的,但卡尔的答案设置了
-server
标志后速度要快得多。此外,米凯拉的服务器模式更具竞争力(尽管仍然比卡尔/马克的慢)

获胜者:MarkPeters

服务器,32位JVM 获胜者:卡尔

服务器(隐式或显式),64位JVM 获胜者:64位

注意:据我所知,没有可比的64位JVM可以在非服务器模式下运行:

64位Java中是否同时提供客户端和服务器VM模式?

目前只有JavaHotSpot服务器VM支持64位操作,并且-Server选项在使用-d64时是隐式的。这将在将来的版本中更改


这个版本怎么样

public static int decompose(long[] buffer, long base) {
    int count = 0;

    if (0 != (base & 1)) {
        buffer[count++] = 1;
    }

    base >>>= 1;

    for (long bit = 1; 0 < bit && bit <= base; ) {
        if (0 < (base & bit)) {
            buffer[count++] = (bit <<= 1);
        }
    }
    return count;
}
公共静态int分解(长[]缓冲区,长基){
整数计数=0;
如果(0!=(基本值和1)){
缓冲区[计数++]=1;
}
基>>>=1;

对于(long bit=1;0
    protected int decompose(long[] buffer, long base) {
        int count = Long.bitCount(base);
        for (int i = 0; i < count; i++) {
            base -= (buffer[i] = Long.lowestOneBit(base));
        }
        return count;
    }


(或等效的xor版本),因为它可以使用本机处理器操作执行64位比较。

经过一些比较后(必须通过消除缓冲区分配使原来的比较更加精确),我上面给出的答案与您的答案相差不到百分之一。消除分配会使速度提高约五分之一,但这只有在缓冲区可以重用时才有用。此外,将while循环向上滚动到单个语句(
while((base&=~(buffer[count++]=base&(-base))!=0)
似乎可以稍微提高性能(在运行该方法的几分钟内可以提高几个百分点)。可能是因为消除了
掩码
赋值?这不适用于
中的任意位位置(例如,100101101的
结果长度为5)。你能发布你的测试工具吗?@Mark:edited in;
BitTwiddling
是一个静态工具类,它有分解方法。这不是一个太好的测试工具。它不会隔离很多应该隔离的东西。它也不会一个接一个地运行它们来忽略热点编译的有效性请看我发布的问题。另外,在测试类集合中
compareIterations=Integer.MAX_VALUE>>2
感谢您发布这篇文章;我有一个问题-因为
缓冲区
从未被读取(仅被覆盖),编译器可能会优化掉它的任何副作用吗?或者这是通过与控制方法进行比较来解释的吗?@Carl:我做了一些更改,包括在最后一次小迭代后读取缓冲区,以及在大迭代之间随机化数据。我认为现在任何东西都不可能优化掉。是的,控制是一个好方法指示什么都不是。我想把它添加到测试中,但它似乎永远不会终止…除非它真的很糟糕。我想你一定有一个无限循环或什么的。@马克·彼得斯,是的,你是对的;第一个版本不会在设置了最高位且缓冲区没有用完的情况下终止…第二个版本没有这个问题。我将编辑第一个以使其终止。事实上,我使用了符号位,因此比较不太有效。@Carl:我将其添加到测试中,但正如您在输出中看到的,您经常会得到错误的结果。@Carl,在最新版本中,符号位应该不是问题。我通过将for循环压缩为w,使我的值稍微提高了一点ell(一直快10毫秒)-不知道为什么:
for(int i=0;我也不觉得偷东西丢脸-这就是我想问的问题!-@Carl:这似乎在服务器模式下没有什么区别。我还试图找出为什么使用
Long.bitCount()预计算计数
比while(0!=(base-=(buffer[count++]=Long.lowstonebitset(base))更好
。最后发现这是因为后者需要长时间比较,而您的需要整数比较。我不认为这可以弥补不必要的计算。@Carl:是的,我确认了我上面的评论,并发现在64位JVM上,
long.bitCount()
调用节省了时间,因为长时间的64位比较可以在64位体系结构上本机执行。啊,这是有道理的-我怀疑@mikera的速度最快(因为您上次编辑的是他的
,而
是压缩的,并且是一个库调用,而不是直接计算最低位(
base&(-base)
)?关于32位与64位JVM的良好学习经验。
Control took 41.175272 ms - last base: 0
Carl took 691.966919 ms - last base: 5852835112840111303
MarkPeters took 642.230253 ms - last base: 5852835112840111303
MarkPetersServer64Bit took 742.594626 ms - last base: 5852835112840111303
Rsp2 took 3886.203787 ms - last base: 5852835112840111303
Mikera took 1044.451494 ms - last base: 5852835112840111303
Control took 2.354383 ms - last base: 0
Carl took 508.687401 ms - last base: 338317437500027646
MarkPeters took 521.831297 ms - last base: 338317437500027646
MarkPetersServer64Bit took 727.052206 ms - last base: 338317437500027646
Rsp2 took 3811.75662 ms - last base: 338317437500027646
Mikera took 665.252599 ms - last base: 338317437500027646
Control took 0.007186 ms - last base: 0
Carl took 543.701859 ms - last base: -8898262206218882664
MarkPeters took 439.706079 ms - last base: -8898262206218882664
MarkPetersServer64Bit took 391.831055 ms - last base: -8898262206218882664
Rsp2 took 1861.40449 ms - last base: -8898262206218882664
Mikera took 435.964319 ms - last base: -8898262206218882664
public static int decompose(long[] buffer, long base) {
    int count = 0;

    if (0 != (base & 1)) {
        buffer[count++] = 1;
    }

    base >>>= 1;

    for (long bit = 1; 0 < bit && bit <= base; ) {
        if (0 < (base & bit)) {
            buffer[count++] = (bit <<= 1);
        }
    }
    return count;
}
public static int decompose(long[] buffer, long base) {
    int count = 0;

    for (long bit = 1; 0 != base; bit <<= 1, base >>>= 1) {
        if (0 < (base & 1)) {
            buffer[count++] = bit;
        }
    }
    return count;
}
    protected int decompose(long[] buffer, long base) {
        int count = Long.bitCount(base);
        for (int i = 0; i < count; i++) {
            base -= (buffer[i] = Long.lowestOneBit(base));
        }
        return count;
    }
    protected int decompose(long[] buffer, long base) {
        int count = 0;
        while ( 0 != (base -= (buffer[count++] = Long.lowestOneBit(base))));
        return count;
    }