2017-01-03 7 views
5

erstellt I Funktionen dyst und dystryb:Indexing in r, Probleme mit einigen Punkten

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) 
} 

Nach Aufruf der Funktion dystryb ich dieses:

> 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 

Warum diese Funktion arbeitet für nicht Argument 30 und 59? Natürlich geht es nicht darum, Funktionen zu machen, die einen Vektor von "1" machen, sondern ich wollte klarstellen, wo das Problem liegt.

+0

Ich glaube, es hat damit zu tun, wie 0,3 intern gespeichert wird. Da es sich um eine wiederkehrende Zahl handelt, variiert die Multiplikation mit 100 um ein Vielfaches. Könnte sein. nur ein Gedanke –

Antwort

1

Die Ursache ist numerische Präzision. Siehe SO post für eine R-verwandte Diskussion. Die Links, die der @ Dirk-eddelbuettel enthält, liefern einen Hintergrund sowohl für R als auch für einen der relevantesten Artikel über numerische Präzision in der Computertechnik im Allgemeinen. This post bietet eine detailliertere allgemeine Antwort auf SO bezogen auf die Informatik hinter diesem Problem.

Um zu zeigen, dass die Ursache die numerische Genauigkeit ist, berücksichtigen Sie die Reihenfolge, die Sie erstellt haben. Zuerst der Standardausdruck der Sequenz.

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 

Alles sieht gut aus. Drucken Sie nun Ihre Sequenz aus und geben Sie R an, um 16 Ziffern anzuzeigen.

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 

Sie sehen, dass ‚30‘ den Wert von 29,999999999999996 und ‚59‘ speichert den Wert von 58,999999999999993 gespeichert. Wenn wir nun diese Sequenz als Ganzzahl ausgeben, erhalten wir die folgende Ausgabe.

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 

Diese Zwangs-Funktion übersetzt 29,999999999999996 bis 29 und 58,999999999999993 bis 58, im wesentlichen eine Trunkierung durchführt. In Ihrem Code werden das 29. und das 58. Element zweimal referenziert, während das 30. und das 59. Element überhaupt nicht referenziert werden.

In dieser Situation ist die Ausgabe identisch mit der Verwendung der floor-Funktion.

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

Eine Lösung für Ihr Problem ist round vor dem Gießen die Sequenz zu verwenden, um integer.

+0

Diese Lösung war wirklich hilfreich. Ich dachte über numerische Präzision nach, aber ich konnte nicht herausfinden, wie ich das verbessern könnte. Vielen Dank! – Aga

+0

Sicher, numerische Genauigkeitsprobleme können auf unerwartete Weise auftreten. – lmo

1

Das folgende zeigt genau, was passiert ist, Sie werden Nullen an den Standorten 15, 29, ... wegen Gleitkomma-Präzisionsfehler haben.

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