繁体   English   中英

r中的索引,有些问题

[英]Indexing in r, problems with some points

我创建了函数dystdystryb

dyst<- function(t,x)
{
  f<-1
  return(f)
}
dystryb<- function(x)
{
  x<-sort(x)
  s<- numeric(101)
  u<-seq(0,1, by = 0.01)
  for (t in u)
  {
    s[t*100+1]<-dyst(t,x)
  }
  return(s)
}

在调用函数dystryb我得到了这个:

> x<-c(1,2,3,4,5,6,7)
> dystryb(x)
  [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 [51] 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[101] 1

为什么这个函数不适用于参数30和59? 当然,它不是要创建一个函数,它使“1”的向量,但我想说清楚,问题出在哪里。

根本原因是数值精度。 请参阅此SO帖子以进行与R相关的讨论。 @ Dirk-eddelbuettel包含的链接提供了R的背景和一般涉及计算数值精度的最相关的论文之一。 这篇文章提供了与此问题背后的计算机科学有关的SO的更详细的一般答案。

要显示根本原因是数值精度,请考虑您创建的序列。 首先,默认打印出序列。

print(seq(0,1, by = 0.01) * 100 + 1)
  [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19
 [20]  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38
 [39]  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57
 [58]  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76
 [77]  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95
 [96]  96  97  98  99 100 101

一切都很好看。 现在,打印出你的序列告诉R显示16位数字。

print(seq(0,1, by = 0.01) * 100 + 1, digits=16)
  [1]   1.000000000000000   2.000000000000000   3.000000000000000
  [4]   4.000000000000000   5.000000000000000   6.000000000000000
                                  ...
 [25]  25.000000000000000  26.000000000000000  27.000000000000000
 [28]  28.000000000000000  29.000000000000004  29.999999999999996
 [31]  31.000000000000000  32.000000000000000  33.000000000000000
 [34]  34.000000000000000  35.000000000000000  36.000000000000000
 [37]  37.000000000000000  38.000000000000000  39.000000000000000
 [40]  40.000000000000000  41.000000000000000  42.000000000000000
 [43]  43.000000000000000  44.000000000000000  45.000000000000000
 [46]  46.000000000000000  47.000000000000000  48.000000000000000
 [49]  49.000000000000000  50.000000000000000  51.000000000000000
 [52]  52.000000000000000  53.000000000000000  54.000000000000000
 [55]  55.000000000000000  56.000000000000007  57.000000000000007
 [58]  58.000000000000007  58.999999999999993  60.000000000000000
                               ...
[100] 100.000000000000000 101.000000000000000

你看到'30'存储了29.999999999999996的值,'59'存储了值58.999999999999993。 现在,如果我们将此序列转换为整数,我们将获得以下输出。

print(as.integer(seq(0,1, by = 0.01) * 100 + 1))
  [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19
 [20]  20  21  22  23  24  25  26  27  28  29  29  31  32  33  34  35  36  37  38
 [39]  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57
 [58]  58  58  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76
 [77]  77  78  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95
 [96]  96  97  98  99 100 101

该强制函数将29.999999999999996转换为29和58.99999999999999993至58,基本上执行截断。 因此,在您的代码中,第29和第58个元素被引用两次,而第30和第59个元素根本没有被引用。

在这种情况下,输出与使用floor功能相同。

identical(trunc(seq(0,1, by = 0.01) * 100 + 1), floor(seq(0,1, by = 0.01) * 100 + 1))
[1] TRUE

解决特定问题的一种方法是在将序列转换为整数之前使用round

identical(1:101, as.integer(round(seq(0,1, by = 0.01) * 100 + 1)))
[1] TRUE

以下显示究竟发生了什么,由于浮点精度误差,您将在位置15,29,...处有零。

which(seq(0,1, by = 0.01)*100+1 != 1:101)
# [1] 15 29 30 56 57 58 59

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM