r中的索引,有些问题

Aga*_*Aga 5 indexing for-loop r function

我创建了函数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)
}
Run Code Online (Sandbox Code Playgroud)

调用函数后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
Run Code Online (Sandbox Code Playgroud)

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

lmo*_*lmo 1

根本原因是数值精度。有关 R 相关的讨论,请参阅此SO 帖子。@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
Run Code Online (Sandbox Code Playgroud)

一切看起来都不错。现在,打印出您的序列,告诉 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
Run Code Online (Sandbox Code Playgroud)

您会看到“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
Run Code Online (Sandbox Code Playgroud)

此强制转换函数将 29.999999999999996 转换为 29,将 58.999999999999993 转换为 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
Run Code Online (Sandbox Code Playgroud)

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

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