【问题标题】:How to reverse a number in R如何反转R中的数字
【发布时间】:2016-03-06 09:42:15
【问题描述】:

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

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

想要的输出是n=321

【问题讨论】:

  • 您可以考虑发布示例输入和所需的输出吗?倒车不就是换个顺序吗?
  • 虽然这可能不是最好的方法,但我猜你正在尝试做paste(rev(strsplit(as.character(n),"")[[1]]), collapse = "")。尽管如前所述,最好提供可重现的示例和所需的输出。
  • 谢谢你们。我刚刚更新了我的问题,包括输入和所需的输出。
  • 对于这样的问题,我想首先要看的地方是"mathematics" 社区——所以,你可以使用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)。您可以存储一些计算以避免重复它们。

标签: r


【解决方案1】:

我觉得反转整数应该留在整数世界而不是进入字符串操作世界。在 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”确实是“整数”(我假设“双”在传递给函数之前会自动强制转换)那么原始的“x”将修改。
  • @alexis_laz 我不确定你的意思。你怎么能反转12.3?或者在这种情况下你的ff 工作而这不会? Reverse_CPP2(as.double(c(12, 24))) 也可以正常工作。虽然Reverse_CPP2(as.double(12.3)) 确实会转换为整数,而ff(12.3) 会返回一些其他结果。不管怎样,我不明白你的评论。
  • 我指的是 'typeof's;参见-例如-x1 = 12; Reverse_CPP2(x1); x1; x2 = 12L; Reverse_CPP2(x2); x2
  • @alexis_laz 哇,我不知道那里发生了什么。你能指出一些关于这个问题的文件吗?所以基本上是说函数修改了 x ?
  • 我猜“Writing R Extensions”会警告修改输入。在这种情况下,我相信,当输入的“typeof”与预期不匹配时,“Rcpp”会自动使用(?)排序的coerceVector(返回不同的对象),而当它匹配时,指向R对象的相同指针被操纵。 (我想在这种情况下,只需将 x[i] 保存到 tmp 即可解决此问题。
【解决方案2】:

对于整数可以使用n &gt; 9 this function

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 作为输入。

【讨论】:

    【解决方案3】:

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

    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) 
    }
    

    【讨论】:

      猜你喜欢
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多