2017-01-03 46 views
5

我創建功能dystdystryb索引r中,存在的問題與一些點

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」,但我想說清楚,問題在哪裏。

+0

我認爲這與0.3如何在內部存儲有關。由於它是經常性的數字,乘以100會稍微改變它。也許。只是一個想法 –

回答

1

根本原因是數值精度。有關R相關討論,請參閱此SO post。 @ Dirk-eddelbuettel包含的鏈接爲R和一般覆蓋數值精度的最相關論文提供了背景。 This post提供了與這個問題背後的計算機科學有關的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的價值和58.999999999999993「​​59」存儲的值。現在,如果我們把這個序列作爲一個整數,我們得到下面的輸出。

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.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 

一個解決您的具體問題是鑄造成整數序列之前,使用round

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

這個解決方案真的很有幫助。我想過數值精度,但我無法弄清楚,如何改善這一點。萬分感謝! – Aga

+0

當然,數值精度問題可能會以意想不到的方式出現。 – lmo

1

下面顯示了發生了什麼事情,因爲浮點精度錯誤,您將在位置15,29 ......處有零。

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