从.5开始

时间:2012-10-02 10:33:04

标签: r rounding r-faq

是的我知道为什么我们总是四舍五入到最近的偶数,如果我们在两个数字的确切中间(即2.5变为2)。但是,当我想为某些人评估数据时,他们不希望出现这种行为。获得这个的最简单方法是什么:

x <- seq(0.5,9.5,by=1)
round(x)

为1,2,3,...,10而不是0,2,2,4,4,......,10。

编辑:要清除:舍入后1.4999应为1。 (我认为这很明显)

8 个答案:

答案 0 :(得分:52)

这不是我自己的功能,不幸的是,我找不到我目前所处的位置(最初在Statistically Significant blog发现是匿名评论),但它应该帮助你所需要的。

round2 = function(x, n) {
  posneg = sign(x)
  z = abs(x)*10^n
  z = z + 0.5
  z = trunc(z)
  z = z/10^n
  z*posneg
}

x是您要舍入的对象,n是您要舍入的位数。

示例

x = c(1.85, 1.54, 1.65, 1.85, 1.84)
round(x, 1)
# [1] 1.8 1.5 1.6 1.8 1.8
round2(x, 1)
# [1] 1.9 1.5 1.7 1.9 1.8

答案 1 :(得分:32)

如果你想要的行为与round完全相同,除了那些xxx.5值,试试这个:

x <- seq(0, 1, 0.1)
x
# [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
floor(0.5 + x)
# [1] 0 0 0 0 0 1 1 1 1 1 1

答案 2 :(得分:5)

这似乎有效:

rnd <- function(x) trunc(x+sign(x)*0.5)

Ananda Mahto的回应似乎是这样做的,而且更多 - 我不确定他的回答中的额外代码是什么?或者,换句话说,我无法弄清楚如何打破上面定义的rnd()函数。

示例:

seq(-2, 2, by=0.5)
#  [1] -2.0 -1.5 -1.0 -0.5  0.0  0.5  1.0  1.5  2.0
round(x)
#  [1] -2 -2 -1  0  0  0  1  2  2
rnd(x)
#  [1] -2 -2 -1 -1  0  1  1  2  2

答案 3 :(得分:5)

正如@CarlWitthoft在评论中所说,这是?round中提到的IEC 60559标准:

  

请注意,为了四舍五入,预计将使用IEC 60559标准,“转到偶数位”。因此,round(0.5)为0,round(-1.5)为-2。但是,这取决于OS服务和表示错误(因为例如0.15没有精确表示,舍入规则适用于所表示的数字而不是打印数字,因此舍入(0.15,1)可以是0.1或0.2 )。

Greg Snow的additional explanation

  

这一轮甚至统治背后的逻辑是我们正在努力   代表一个潜在的连续值,如果x来自真实的   连续分布,则x == 2.5为0的概率为   2.5可能已经从2.45和2.54999999999999之间的任何值进行了一次...,如果我们使用我们在小学学习的0.5规则的舍入,则双舍入意味着值   在2.45和2.50之间将全部变为3(首先是圆形的   到2.5)。这往往会使估计偏向上升。要删除   我们需要在四舍五入到2.5之前回归(这是   通常不可能是不切实际的,或者只是将一半的时间和   向下舍入一半的时间(或者更好的是与...成比例   我们有多大可能看到低于或高于2.5的值四舍五入为2.5,但是   大多数基础发行版将接近50/50)。该   随机方法是随机获得圆函数   选择哪种方式来舍入,但确定性类型则不是   对此感到满意,所以选择了“圆到均匀”(圆到奇数)   应该是相同的)作为一个一致的规则,圆形和   大约50/50。

     

如果您正在处理2.5可能代表精确数据的数据   价值(例如金钱),那么你可以通过乘以所有来做得更好   值为10或100并以整数形式工作,然后仅转换回来   用于最终印刷。请注意,2.50000001轮到3,所以如果你   保持更多的精度数字,直到最后的打印,然后四舍五入   将进入预期的方向,或者您可以添加0.000000001(或   在四舍五入之前,你的价值就是其他小数字,但那可以   向上偏向你的估计。

答案 4 :(得分:2)

根据您对数据摆动的舒适程度,这有效:

round(x+10*.Machine$double.eps)
# [1]  1  2  3  4  5  6  7  8  9 10

答案 5 :(得分:2)

此方法:

round2 = function(x, n) {
  posneg = sign(x)
  z = abs(x)*10^n
  z = z + 0.5
  z = trunc(z)
  z = z/10^n
  z*posneg
}
当我们有许多位数的数字时,

似乎不能很好地工作。例如。做round2(2436.845, 2)将给我们2436.84。 trunc(z)函数似乎出现了此问题。

总的来说,我认为这与R存储数字的方式有关,因此truncfloat函数并不总是起作用。我能够以最优雅的方式解决它:

round2 = function(x, n) {
  posneg = sign(x)
  z = abs(x)*10^n
  z = z + 0.5
  z = trunc(as.numeric(as.character(z)))
  z = z/10^n
  (z)*posneg
}

答案 6 :(得分:1)

这模仿了从零到0.5的舍入:

round_2 <- function(x, digits = 0) {
  x = x + abs(x) * sign(x) * .Machine$double.eps
  round(x, digits = digits)
}

round_2(.5 + -2:4)
-2 -1  1  2  3  4  5

答案 7 :(得分:-2)

最好,最简单的解决方案是在数字上加上0.00000001,然后四舍五入。

回合(1.15 + 0.00000001,1)= 1.2