最近算一个数发现R和SAS在round过程中会出现不一致问题,SAS的ROUND函数使用"四舍五入"规则修约,而R的round使用“四舍六入五成双”修约。
当5后有数时,舍5入1;当5后无有效数字时,需要分两种情况来讲:
(1)5前为奇数,舍5入1;
(2)5前为偶数,舍5不进(0是偶数)。
(所以X.XXXX5需要修约掉这个5,那么修约之后的最后一位一定是个偶数)
R语言虽然是四舍六入,但又不完全是,比如:
test<-data.frame(
a=seq(0.105,0.195,by=0.01),
b=round(a,2),
c=sprintf("%.22f",a)
)
test
输出结果如下
a b c
1 0.105 **0.11** 0.1050000000000000099920
2 0.115 0.12 0.1150000000000000049960
3 0.125 0.12 0.1250000000000000000000
4 0.135 0.14 0.1350000000000000088818
5 0.145 **0.15** 0.1450000000000000177636
6 0.155 0.16 0.1550000000000000266454
7 0.165 0.16 0.1650000000000000077716
8 0.175 0.18 0.1750000000000000166533
9 0.185 0.18 0.1849999999999999977796
10 0.195 0.20 0.1950000000000000066613
虽然round函数严格执行了四舍六入五成双,但是R语言默认的double数值又让结果难以预测。
按照道理,当被修约的数是5,且后面无有效数字,则奇进偶不进。
(想起了十几年前在这里看见的一个帖子【请教】round四舍五入问题,可惜了,时过境迁,没这么多活跃的人了。)于是查看了精确值,发现可能是因为双精度结果凛然难以捉摸?
更让人难以琢磨的是,这似乎和储存方式有关,前面的例子用的是data.frame,
直接使用向量:
test<-c(0.105,0.115,0.125,0.135,0.145,0.155,0.165,0.175,0.185,0.195)
test
round(test,2)
您猜怎么着
> test
[1] 0.105 0.115 0.125 0.135 0.145 0.155 0.165 0.175 0.185 0.195
> round(test,2)
[1] 0.10 0.12 0.12 0.14 0.14 0.16 0.16 **0.17** 0.18 0.20
如果单拉出来
> round(0.145,2)
[1] 0.14
> round(0.175,2)
[1] 0.17
使用最近流行的tibble
library(tidyverse)
test<-tibble(
a=seq(0.105,0.195,by=0.01),
b=round(a,2),
c=sprintf("%.22f",a)
)
test
结果也不一样哦
> test
# A tibble: 10 × 3
a b c
<dbl> <dbl> <chr>
1 0.105 0.1 0.1049999999999999961142
2 0.115 **0.11** 0.1149999999999999911182
3 0.125 0.12 0.1250000000000000000000
4 0.135 0.14 0.1350000000000000088818
5 0.145 0.14 0.1449999999999999900080
6 0.155 0.16 0.1549999999999999988898
7 0.165 0.16 0.1649999999999999800160
8 0.175 **0.17** 0.1749999999999999888978
9 0.185 0.18 0.1849999999999999977796
10 0.195 0.2 0.1950000000000000066613
FDA已经开始接受R语言递交的结果了,我有点好奇这个数值修约问题会不会被关注。