当将某些数字与模数函数一起使用时,模数警告可能会完全失去准确性,并且结果不正确

问题描述

我在R中编写了此函数,并且该函数中的模运算符存在一些问题。此函数的目的是,如果数字在小数点后有任何数字,则将1返回n + 1个小数位;否则,对于任何整数,例如,返回1。返回0.1表示1,返回1表示50,依此类推。

代码是

tolerance <- function(x){
  constant <- 1
  if (x < 0){
    constant <- -1
    x <- constant * x
  }
  exponent <- 0
  if (is.numeric(x) & !is.integer(x)) {
    while(x %% 10 > 0) {
      x <- 10 * x
      exponent <- exponent + 1
    }
    return(constant * 10 ^ (-exponent))
  }
}

这些是我得到的结果

> for (i in c(1,0.1,0.11,0.111,0.1111)) {
+   print(tolerance(i))
+ }
[1] 0.1
[1] 0.01
[1] 0.001
[1] 1e-24
[1] 1e-05
Warning messages:
1: In tolerance(i) : probable complete loss of accuracy in modulus
2: In tolerance(i) : probable complete loss of accuracy in modulus
3: In tolerance(i) : probable complete loss of accuracy in modulus
4: In tolerance(i) : probable complete loss of accuracy in modulus

如您所见,异常行为发生在0.111而不是0.1111,因此看来小数位数似乎不会引起奇怪的警告消息和错误的结果。实际上,当我更改数字时,例如,小数点后三位都可以正常工作

> tolerance(5.111)
[1] 1e-04

0.0001是预期的正确结果,因此看来问题只出现在某些数字上。我没有将很大的数字传递给该函数,因为我知道R不能很好地处理具有很大数字的数字数据类型。我通常最多将小数点后6位数字传递给该函数。

问题是否与处理数字时将十进制数字转换为二进制数字有关?还是一共?

我相信是导致模数运算符的部分引起了问题,因为当我在不使用模数运算符的情况下重写此函数时,而是使用字符串操作,代码似乎按预期工作。

有什么想法吗?

解决方法

这本质上是主题why are these numbers not equal?的数百万种变体之一

这只是部分答案,但是请尝试以下操作(调试语句,删除了否定x的代码):

tolerance <- function(x){
  constant <- 1
  exponent <- 0
  if (is.numeric(x) & !is.integer(x)) {
    while(x %% 10 > 0) {          
      x <- 10 * x
      exponent <- exponent + 1
      cat("x ",format(x,digits=22),"\n")
      cat("x %% 10",format(x %% 10,"\n")
    }
    return(constant * 10 ^ (-exponent))
  }
}

对于x = 0.11,

tolerance(0.11)
## x  1.100000000000000088818 
## x %% 10 1.100000000000000088818 
## x  11 
## x %% 10 1 
## x  110 
## x %% 10 0 

在这种情况下,您很幸运,由于缺乏精度,初始浮点噪声(因为0.11不能在有限数目的二进制数字中精确表示)会从末尾掉落。

对于x=0.111,取消的模式是不同的(也是不幸的)。

tolerance(0.111)
x  1.1100000000000000977 
x %% 10 1.1100000000000000977 
x  11.10000000000000142109 
x %% 10 1.100000000000001421085 
x  111.0000000000000142109 
x %% 10 1.000000000000014210855 
x  1110.000000000000227374 
x %% 10 2.273736754432320594788e-13 
x  11100.00000000000181899 
x %% 10 1.81898940354585647583e-12 
x  111000.0000000000145519 
x %% 10 1.455191522836685180664e-11 
x  1110000.000000000232831 
x %% 10 2.328306436538696289062e-10 
x  11100000.00000000186265 
x %% 10 1.86264514923095703125e-09 
x  111000000.0000000149012 
x %% 10 1.490116119384765625e-08 
x  1110000000.000000238419 
x %% 10 2.384185791015625e-07 
x  11100000000.00000190735 
x %% 10 1.9073486328125e-06 
x  111000000000.0000152588 
x %% 10 1.52587890625e-05 
x  1110000000000.000244141 
x %% 10 0.000244140625 
x  11100000000000.00195312 
x %% 10 0.001953125 
x  111000000000000.015625 
x %% 10 0.015625 
x  1110000000000000.125 
x %% 10 0.125 
x  11100000000000002 
x %% 10 2 
x  111000000000000016 
x %% 10 6 
x  1110000000000000128 
x %% 10 8 
x  11100000000000002048 
x %% 10 8 
x  111000000000000016384 
x %% 10 4 
x  1110000000000000131072 
x %% 10 2 
x  11100000000000001048576 
x %% 10 6 
x  111000000000000010485760 
x %% 10 0 
[1] 1e-24

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...