是什么解释R中x.x5的小数点后一位舍入?

时间:2019-06-07 03:08:01

标签: r rounding ieee-754

我正在寻找一种解释,说明如何在R中对这样的序列进行1位小数舍入运算:

seq(1.05, 2.95, by = .1)

在高中时,我会将其四舍五入,即2.05变为2.1。但是R会将其四舍五入为2,以便将小数点后一位舍入。

Round up from .5

上面的stackoverflow答案中的以下舍入函数始终实现高中舍入:

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
}

此代码比较R舍入和从上舍入。

data.frame(cbind(
  Number = seq(1.05, 2.95, by = .1), 
  Popular.Round = round2(seq(1.05, 2.95, by = .1), 1),
  R.Round = round(seq(1.05, 2.95, by = .1), 1)))

使用R舍入时,1.05舍入到1.1,而2.05舍入到2。然后再次将1.95舍入到2,并将2.95舍入到3。

如果它是“四舍五入”,为什么是3,即奇数。

当被问到这种行为时,有没有比“仅仅处理”更好的响应了?

1 个答案:

答案 0 :(得分:2)

阅读时间太长?向下滚动

这对我个人来说是一个有趣的研究。根据文档:

  

请注意,对于5的四舍五入,请参见IEC 60559标准(另请参见“ IEEE   754”),则应使用“转到偶数位”。因此   round(0.5)为0,round(-1.5)为-2。但是,这取决于   OS服务和表示错误(因为0.15不会   精确表示,四舍五入规则适用于   数字而不是印刷的数字,因此舍入(0.15,1)可能是   0.1或0.2)。

     

四舍五入为负数意味着四舍五入为   十,因此例如round(x,digits = -2)舍入到最接近的值   一百。

     

对于数字,如果识别出的数字值为1 ... 22,并且不丢失   值四舍五入到该范围内最接近的整数。复杂   四舍五入以保留指定数字位数   更大的组件。向量的每个元素都经过四舍五入   不同于打印。

首先,您问“如果它是“舍入到偶数”,为什么它是3,即奇数。” 要清楚地说明,舍入到偶数规则适用于舍入5。如果运行round(2.5)round(3.5),则R分别返回2和4。

如果您在这里https://stat.ethz.ch/pipermail/r-help/2008-June/164927.html,则会看到以下响应:

  

四舍五入规则的逻辑在于,我们试图   表示基础连续值,如果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(或   四舍五入到您的值,但这可以   向上偏移您的估算值。

简短答案:如果您始终将5s向上舍入,则数据会向上偏移。但是,如果您四舍五入,那么四舍五入的数据将变得平衡。

让我们使用您的数据进行测试:

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 <- data.frame(cbind(
  Number = seq(1.05, 2.95, by = .1), 
  Popular.Round = round2(seq(1.05, 2.95, by = .1), 1),
  R.Round = round(seq(1.05, 2.95, by = .1), 1)))

> mean(x$Popular.Round)
[1] 2.05
> mean(x$R.Round)
[1] 2.02

使用更大的样本:

x <- data.frame(cbind(
  Number = seq(1.05, 6000, by = .1), 
  Popular.Round = round2(seq(1.05, 6000, by = .1), 1),
  R.Round = round(seq(1.05, 6000, by = .1), 1)))

> mean(x$Popular.Round)
[1] 3000.55
> mean(x$R.Round)
[1] 3000.537