圆形,但 .5 应该是地板
round but .5 should be floored
来自 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
有没有快速的方法?
检查 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
此函数的工作原理是查找小数部分等于 0.5
的元素,并在四舍五入前向它们添加一个小的负数,以确保它们向下舍入。 (它依赖于——无害但以稍微混淆的方式——基于这样一个事实,即 R 中的布尔向量在乘以一个数字时将被转换为 0
和 1
的向量矢量。)
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
(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
我也要加入马戏团:
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
根据 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
这种四舍五入的应用是什么?
来自 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
有没有快速的方法?
检查 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
此函数的工作原理是查找小数部分等于 0.5
的元素,并在四舍五入前向它们添加一个小的负数,以确保它们向下舍入。 (它依赖于——无害但以稍微混淆的方式——基于这样一个事实,即 R 中的布尔向量在乘以一个数字时将被转换为 0
和 1
的向量矢量。)
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
(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
我也要加入马戏团:
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
根据 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
这种四舍五入的应用是什么?