Select十进制数的所有二进制邻居

Select all binary neighbors of decimal number

假设我有一个十进制格式的数字:5

它的二进制版本是:00101

我想写一个取十进制数的函数x

和returns所有其他十进制数字与原始数字有单个数字差异(二进制形式):

所以对于上面的例子,邻居是:

10101 01101 00111 00001 00100

对应的小数为:

21 13 7 1 4

我想要一个计算效率高的解决方案,即使我说一百万个数字也不会花费很长时间。

这可以吗?

我想你是在问如何将数字 5 作为输入并 return 所有相邻的二进制值。为此,您需要将数字转换为有用的二进制格式(只是您要翻转的位),翻转每个位,然后 return 结果:

library(R.utils)
bin.neighbors <- function(x, num.neighbors=NA) {
  # Get the bits with the appropriate amount of padding
  bits <- as.numeric(unlist(strsplit(intToBin(x), "")))
  if (!is.na(num.neighbors) & num.neighbors > length(bits)) {
    bits <- c(rep(0, num.neighbors-length(bits)), bits)
  }

  # Build a matrix where each column is a bit vector of a neighbor
  mat <- matrix(bits, length(bits), length(bits))
  diag(mat) <- 1-diag(mat)

  # Return the decimal values of the neighbors using strtoi
  apply(mat, 2, function(x) strtoi(paste0(x, collapse=""), 2))
}
bin.neighbors(5, 5)
# [1] 21 13  1  7  4

因为每个数字都有多个二进制表示,前导0的个数不同(例如5可以表示为101、0101、00101、000101、0000101等),所以我添加了一个参数num.neighbors指定函数输出向量的长度。您可以传递 NA 以获得等于输入的二进制表示中不带前导零的位数的输出向量。

我不知道反复试验是如何让我来到这里的,但它看起来是有效的,除非我弄乱了二进制和小数:

bin_neighs = function(x, n) bitwXor(x, (2 ^ (0:(n - 1))))
bin_neighs(5, 5)
#[1]  4  7  1 13 21

这是使用 magrittr 管道的另一种方法:

binNeighbours <- function(a, numNeighbours = ceiling(log2(a))) {
    rep(a, numNeighbours) %>%
    outer(., seq(.) - 1, function(x, y) x %/% (2 ^ y) %% 2) %>%
    `diag<-`(., 1 - diag(.)) %>%
    `%*%`(2 ^(0:(nrow(.) - 1))) %>%
    `[`(, 1)
  }