如何在R中反转一个数字

7

我想编写一个函数来反转任何数字的顺序。以下是我所拥有的,但它不起作用。请帮助我!

n=123
rev_number=function(n){
 m=strsplit(as.character(n),"")
 if (m==rev(m)) print("reversed number")
}

期望的输出是 n=321

你能否考虑发布样例输入和期望输出呢?反转不就是改变顺序吗? - Konrad
1
虽然这可能不是最好的方法,但我猜你正在尝试做 paste(rev(strsplit(as.character(n),"")[[1]]), collapse = "")。但正如提到的那样,最好提供一个可重现的示例和期望的输出。 - David Arenburg
谢谢大家。我刚刚更新了我的问题,附上了输入和期望的输出。 - Cypress
对于这样的问题,我猜第一个地方可以看看是"数学"社区 - 所以,你可以使用ff = function(x) x * 10^floor(log10(x)) - 99 * sum(floor(x * 10^(-seq_len(floor(log10(x))))) * 10^(floor(log10(x)) - seq_len(floor(log10(x))))); ff(4568742)。你可以存储一些计算以避免重复。 - alexis_laz
5个回答

12

我觉得反转整数应该留在整数世界,而不是进入字符串操作的世界。在R中似乎没有内置函数来完成这个任务,因此我们可以使用Rcpp包创建一个函数。下面是一个例子:

library(Rcpp)
cppFunction('int Reverse_CPP(int x) {
  int reverse = 0;
  while(x != 0) {
        int remainder = x%10;
        reverse = reverse*10 + remainder;
        x/= 10;
    }
  return reverse ; 
}')

Reverse_CPP(1234)
# [1] 4321

以下是向量化版本:
cppFunction('IntegerVector Reverse_CPP2(IntegerVector x) {
  int n = x.size();
  IntegerVector out(n);
  IntegerVector xx = clone(x); // Will need this if you don"t want to modify x in place

  for (int i = 0; i < n; ++i){
    int reverse = 0;
    while(xx[i] != 0) {
       int remainder = xx[i]%10;
       reverse = reverse*10 + remainder;
       xx[i]/= 10;
    }
    out[i] = reverse;
   }

   return out;

}')

Reverse_CPP2(c(12345, 21331, 4324234, 4243))
# [1]   54321   13312 4324234    3424

请注意,我不得不添加IntegerVector xx = clone(x);,因此大大减慢了函数的速度(请参见@alexis_laz的评论),否则Rcpp会通过引用修改原始的x。如果您传递一个裸向量或者您不关心原始向量是否被修改,那么您不需要这个。
一些与其他矢量化字符串操作函数的基准测试
Stringi <- function(x) as.integer(stringi::stri_reverse(x))

Base <- function(x) {
  as.integer(vapply(lapply(strsplit(as.character(x), "", fixed = TRUE), rev),
                    paste, collapse = "", FUN.VALUE = character(1L)))
}


library(microbenchmark)
set.seed(123)
x <- sample(1e3L:1e7L, 1e5, replace = TRUE)

microbenchmark(
               Base(x),
               Stringi(x),
               Reverse_CPP2(x)
)

# Unit: milliseconds
#            expr        min         lq      mean     median          uq         max neval cld
#         Base(x) 855.985729 913.602215 994.60640 976.836206 1025.482170 1867.448511   100   c
#      Stringi(x)  86.244426  94.882566 105.58049 102.962924  110.334702  179.918461   100  b 
# Reverse_CPP2(x)   1.842699   1.865594   2.06674   1.947703    2.076983    6.546552   100 a  

在第二个函数中需要注意的是 - 如果输入的 'x' 确实是 "integer"(我假设一个 "double" 在传递给函数之前将自动强制转换),那么原始的 'x' 将被修改。 - alexis_laz
我猜“编写R扩展”警告我们不要修改输入。在这种情况下,我相信,“Rcpp”自动使用coerceVector(返回一个不同的对象)当输入的'typeof'与期望的不匹配时,而当匹配时,相同指向R对象的指针被操作。(我想在这种情况下,只需将x [i]保存到tmp中即可解决这个问题)。 - alexis_laz
@alexis_laz 嗯...所以我想我需要添加 IntegerVector xx = Rcpp::clone(x) ; 或者其他什么... - David Arenburg
不需要在每次迭代中重复,只需将x[i]保存到临时“int”中并修改即可。 - alexis_laz
@alexis_laz 我在这里找到了Dirk解决这个问题的方法。我也会尝试你的建议,谢谢。 - David Arenburg
显示剩余3条评论

2

这是我通过扩展您的代码尝试的结果

n=-123
rev_number=function(n){
  if(n>0)
  return(as.integer(paste0(rev(unlist(strsplit(as.character(n), ""))), collapse = "")))
  else{
    return(-as.integer(paste0(rev(unlist(strsplit(as.character(abs(n)), ""))), collapse = "")))
  }
}
rev_number(n)

如果要处理负数,可以使用if else语句。首先将整数转换为字符,然后使用strsplit函数将数字拆分。接着使用unlist函数将列表转换为向量。然后我们可以使用rev函数反转向量并使用paste函数合并向量。最后使用as.integer函数将字符串转换为整数。

如果不想将数字转换为字符,下面的方法不需要任何额外的包,但只适用于正整数。

reverse_number <- function(n){
rev <- 0

while (n > 0) {
  r <- n %% 10
  rev <- rev * 10 + r
  n <- n %/% 10
}

return(rev)
}
reverse_number(134576)

1

对于大于9的整数,可以使用这个函数

reverse_int <- function(n) {
  t1 <- floor(log10(n))
  t2 <- 0
  for (i in t1:1) t2 <- t2 + floor(n/10^i) * 10^(t1-i)
  return(n*10^t1 - 99*t2)
}
reverse_int(678754)
#[1] 457876

请注意,该函数未向量化;它只接受一个参数n作为输入。

1

一个R函数,基于10的连续幂次的整数除法来反转数字。这是在与回文数字相关的学校项目中出现的。

Reverse_number <- function(x){ 
  n <- trunc(log10(x)) # now many powers of 10 are we dealing with 
  x.rem <- x # the remaining numbers to be reversed 
  x.out <- 0 # stores the output 
  for(i in n:0){
  x.out <- x.out + (x.rem %/% 10^i)*10^(n-i) # multiply and add 
  x.rem <- x.rem - (x.rem %/% 10^i)*10^i # multiply and subtract 
  } 
return(x.out) 
}

0

以下是使用 utf8ToIntsubstring 的其他基本 R 选项

> n <- 123478634

> as.integer(intToUtf8(rev(utf8ToInt(as.character(n)))))
[1] 436874321

> as.integer(paste0(substring(n, nchar(n):1, nchar(n):1), collapse = ""))
[1] 436874321

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接