Algorithm 具有最大尾随零位数的间隔中的整数

Algorithm 具有最大尾随零位数的间隔中的整数,algorithm,scala,bit-manipulation,Algorithm,Scala,Bit Manipulation,Seekend是一种高效的算法,可在二进制表示中具有最大尾随零数的区间[a,b]中查找唯一整数(a和b为整数>0): 等等。首先看看你的时间间隔内是否有二的幂。如果至少有一个,则最大的一个获胜 否则,请选择两个中小于最小界限的最大幂 1100000…0在你的范围内吗?如果是,你赢了。如果仍然小于您的最小界限,请尝试1110000…0;否则,如果它大于您的最大界限,请尝试1010000…0 以此类推,直到你赢。这一个可以找到零的数量: // Requires a>0 def mtz(a: I

Seekend是一种高效的算法,可在二进制表示中具有最大尾随零数的区间
[a,b]
中查找唯一整数(
a
b
为整数>0):


等等。

首先看看你的时间间隔内是否有二的幂。如果至少有一个,则最大的一个获胜

否则,请选择两个中小于最小界限的最大幂

1100000…0在你的范围内吗?如果是,你赢了。如果仍然小于您的最小界限,请尝试1110000…0;否则,如果它大于您的最大界限,请尝试1010000…0


以此类推,直到你赢。

这一个可以找到零的数量:

// Requires a>0
def mtz(a: Int, b: Int, mask: Int = 0xFFFFFFFE, n: Int = 0): Int = {
  if (a > (b & mask)) n
  else mtz(a, b, mask<<1, n+1)
}
//需要>0
def mtz(a:Int,b:Int,掩码:Int=0xFFFFFE,n:Int=0):Int={
如果(a>(b和掩码))n
else mtz(a、b、掩码(b和掩码))b和(掩码>>1)

else nmtz(a,b,mask作为结论,这里是我的Rex'答案的变体,它给出了中心值和一个'范围',它是距离中心两个距离的最小幂,在一个方向覆盖
a
,在另一个方向覆盖
b

@tailrec def binSplit(a: Int, b: Int, mask: Int = 0xFFFFFFFF): (Int, Int) = {
  val mask2 = mask << 1
  if (a > (b & mask2)) (b & mask, -mask)
  else binSplit(a, b, mask2)
}

def test(): Unit = {
  val Seq(r1, r2) = Seq.fill(2)(util.Random.nextInt(0x3FFFFFFF) + 1)
  val (a, b) = if (r1 <= r2) (r1, r2) else (r2, r1)
  val (center, extent) = binSplit(a, b)
  assert((center >= a) && (center <= b) && (center - extent) <= a &&
         (center - extent) >= 0 && (center + extent) > b, (a, b, center, extent))
}

for (i <- 0 to 100000) { test() }
@tailrec def binSplit(a:Int,b:Int,mask:Int=0xFFFFFFFF):(Int,Int)={
val mask2=遮罩(b&mask2))(b&mask2,-遮罩)
else binSplit(a、b、mask2)
}
def测试():单位={
val Seq(r1,r2)=Seq.fill(2)(util.Random.nextInt(0x3FFFFFFF)+1)
val(a,b)=如果(r1=a)&(中心b,(a,b,中心,范围))
}

因为(我决定接受雷克斯的挑战,生产更快的产品。:-)


哇,太棒了!你是刚想出这个还是有那个?这是一种标准的算法,有名字吗?@Rex:这看起来很接近我的叙述版本。如果是一样的话,那么在每一步之后,你都在减少尾随的零的数量。所以根本不需要搜索?@Sciss-我刚刚想出了这个。它可能是以第一个提出并命名它的人的名字命名的。@John-没有必要做“如果少,如果多”的事情,因为屏蔽总是减少b。@Rex我不是Scala程序员,所以我需要研究你的代码。:)但我不理解你关于“你可以进行二进制搜索”的评论@John-我从
0xFFFFFFFF-((1好,谢谢。所以Rex'和你的方法都会采用最坏的情况O(logn),其中n是最大位数(32)。我希望有一些O(1)魔法,但这实际上很好。位中不是O(n)吗?我可以看到O(logn)如果你认为n是,比如说,你的区间最大值?或者我把事情搞糊涂了?是的,没错。因为我的数字有一个固定的字长(不变的位数),这实际上意味着它是O(1)关于interval.nice!的大小,使用10000000的循环和预先计算的随机间隔,mtz在REPL中预热后运行约0.74秒,mtz2在REPL中运行约0.52秒,这是大约30%的加速。nice:)(顺便说一句,这个问题是我第一次在欣赏签名轮班操作员的地方做一些小游戏……@Rex,事实上,我也是。:-)我发现我错过了上面代码中的
f
定义。周一我会看看我的工作桌面上是否还能找到它。
// Requires a>0
def mtz(a: Int, b: Int, mask: Int = 0xFFFFFFFE, n: Int = 0): Int = {
  if (a > (b & mask)) n
  else mtz(a, b, mask<<1, n+1)
}
// Requires a > 0
def nmtz(a: Int, b: Int, mask: Int = 0xFFFFFFFE): Int = {
  if (a > (b & mask)) b & (mask>>1)
  else nmtz(a, b, mask<<1)
}
@tailrec def binSplit(a: Int, b: Int, mask: Int = 0xFFFFFFFF): (Int, Int) = {
  val mask2 = mask << 1
  if (a > (b & mask2)) (b & mask, -mask)
  else binSplit(a, b, mask2)
}

def test(): Unit = {
  val Seq(r1, r2) = Seq.fill(2)(util.Random.nextInt(0x3FFFFFFF) + 1)
  val (a, b) = if (r1 <= r2) (r1, r2) else (r2, r1)
  val (center, extent) = binSplit(a, b)
  assert((center >= a) && (center <= b) && (center - extent) <= a &&
         (center - extent) >= 0 && (center + extent) > b, (a, b, center, extent))
}

for (i <- 0 to 100000) { test() }
// requires a > 0
def mtz2(a: Int, b: Int, mask: Int = 0xffff0000, shift: Int = 8, n: Int = 16): Int = {
  if (shift == 0) if (a > (b & mask)) n - 1 else n
  else if (a > (b & mask)) mtz2(a, b, mask >> shift, shift / 2, n - shift)
  else mtz2(a, b, mask << shift, shift / 2, n + shift)
}
import System.{currentTimeMillis => now}
def time[T](f: => T): T = {
  val start = now
  try { f } finally { println("Elapsed: " + (now - start)/1000.0 + " s") }
}

val range = 1 to 200
time(f((a, b) => mtz(a, b)))
time(f((a, b) => mtz2(a, b)))