【问题标题】:round but .5 should be floored圆形,但 0.5 应该是地板
【发布时间】:2016-01-17 23:49:34
【问题描述】:

来自 R 帮助函数:请注意,要对 5 进行四舍五入,预计将使用 IEC 60559 标准,“转到偶数位”。因此round(0.5) 为 0,round(-1.5) 为 -2。

> round(0.5)
[1] 0
> round(1.5)
[1] 2
> round(2.5)
[1] 2
> round(3.5)
[1] 4
> round(4.5)
[1] 4

但我需要将所有以 .5 结尾的值向下舍入。所有其他值都应该四舍五入,因为它们是由 round() 函数完成的。 示例:

round(3.5) = 3
round(8.6) = 9
round(8.1) = 8
round(4.5) = 4

有没有快速的方法?

【问题讨论】:

  • 为什么不只是ceil(x - 0.5)
  • @DietrichEpp 我来问同样的问题:我觉得你的问题应该是一个答案:)
  • 我们能不能稍等片刻,问一下为什么你想这样做。您在舍入数据集中引入了偏差。手头有什么问题,您为什么认为它需要这种特殊处理?

标签: r rounding


【解决方案1】:

根据 Dietrich Epp 的评论,您可以使用带有偏移量的 ceiling() 函数来获得快速、矢量化、正确的解决方案:

round_down <- function(x) ceiling(x - 0.5)
round_down(seq(-2, 3, by = 0.5))
## [1] -2 -2 -1 -1  0  0  1  1  2  2  3

我认为这比此处显示的许多其他解决方案更快、更简单。

正如 Carl Witthoft 所指出的,与简单的四舍五入相比,这会给您的数据增加更多的偏差。比较:

mean(round_down(seq(-2, 3, by = 0.5)))
## [1] 0.2727273
mean(round(seq(-2, 3, by = 0.5)))
## [1] 0.4545455
mean(seq(-2, 3, by = 0.5))
## [1] 0.5

这种舍入过程的应用是什么?

【讨论】:

  • 这是迄今为止最好的方法。
【解决方案2】:

检查x %% 1 的余数是否等于.5,然后取整或取整:

x <- seq(1, 3, 0.1)
ifelse(x %% 1 == 0.5, floor(x), round(x))
> 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3

【讨论】:

    【解决方案3】:

    我也要加入马戏团:

    rndflr <- function(x) {
      sel <- vapply(x - floor(x), function(y) isTRUE(all.equal(y, 0.5)), FUN.VALUE=logical(1))
      x[sel] <- floor(x[sel])
      x[!sel] <- round(x[!sel])  
      x
    }
    
    rndflr(c(3.5,8.6,8.1,4.5))
    #[1] 3 9 8 4
    

    【讨论】:

    • +1 来自我。使用all.equal() 的唯一答案,恕我直言,这是处理此类情况的正确方法。
    【解决方案4】:

    此函数的工作原理是查找小数部分等于0.5 的元素,并在舍入前向它们添加一个小的负数,以确保它们将向下舍入。 (它依赖于 - 无害但略微混淆的方式 - R 中的布尔向量在乘以数字向量时将转换为 01 的向量。) /p>

    f <- function(x) {
        round(x - .1*(x%%1 == .5))
    }
    
    x <- c(0.5,1,1.5,2,2.5,2.01,2.99)
    f(x)
    [1] 0 1 1 2 2 2 3
    

    【讨论】:

      【解决方案5】:

      函数(not golfed) 非常简单,它检查剩下的小数是否为.5 或更少。实际上,您可以轻松地使其更有用并将0.5 作为参数:

      nice.round <- function(x, myLimit = 0.5) {
        bX <- x
        intX <- as.integer(x)
        decimals <- x%%intX
        if(is.na(decimals)) {
          decimals <- 0
        }
        if(decimals <= myLimit) {
          x <- floor(x)
        } else {
          x <- round(x)
        }
        if (bX > 0.5 & bX < 1) {
          x <- 1
        }
        return(x)
      }
      

      测试

      目前,此函数在 0.5 和 1.0 之间的值无法正常工作。

      > nice.round(1.5)
      [1] 1
      > nice.round(1.6)
      [1] 2
      > nice.round(10000.624541)
      [1] 10001
      > nice.round(0.4)
      [1] 0
      > nice.round(0.6)
      [1] 1
      

      【讨论】:

      • “没有打高尔夫球”——这应该是件的事情吗??
      • @WChargin 绝对不是,我只是表明该函数可以很容易地缩短。
      • 这是来自@Kreuvf 的评论,他参加了编辑此帖子的评论:“目前,此函数在 0.5 和 1.0 之间的值无法正常工作。nice.round(0.6) 返回 0。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多