但是.5应该是圆的

时间:2016-01-17 23:49:34

标签: r rounding

来自R帮助功能:请注意,为了四舍五入,预计将使用IEC 60559标准,“转到偶数位”。因此round(-1.5)为0,> 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 为-2。

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

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

#define MAKE_INSERT_FUNC(__fname, __type, __member)       \
    MyStruct *__fname(MyStruct **root, __type val) {      \
        MyStruct *newNode = malloc(sizeof(MyStruct));     \
        if (newNode) {                                    \
            newNode->next = *root;                        \
            newNode->val.__member = val;                  \
            newNode->type = type;                         \
            *root = newNode;                              \
        }                                                 \
        return newNode;                                   \
    }

有快速的方法吗?

5 个答案:

答案 0 :(得分:28)

Per 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

这种舍入程序的申请是什么?

答案 1 :(得分:20)

检查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

答案 2 :(得分:15)

我也会加入马戏团:

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

答案 3 :(得分:10)

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

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

答案 4 :(得分:8)

函数(非高尔夫)非常简单,并检查剩下的小数是否为.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