2017-01-03 14 views
5

Tôi tạo ra chức năng dystdystryb:Indexing trong r, vấn đề với một số điểm

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

Sau khi gọi chức năng dystryb tôi có được điều này:

> 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 

Tại sao không phải chức năng này làm việc cho lập luận 30 và 59? Tất nhiên nó không phải là về làm cho một chức năng, mà làm cho vector của "1", nhưng tôi muốn làm cho nó rõ ràng, nơi mà vấn đề là.

+0

tôi tin rằng nó phải liên quan đến cách 0.3 đang được lưu trữ nội bộ. Vì đó là số định kỳ, nhân với 100 thay đổi một chút. Có lẽ. chỉ là một ý nghĩ –

Trả lời

1

Nguyên nhân gốc là độ chính xác bằng số. Xem điều này SO post để có cuộc thảo luận liên quan đến R. Các liên kết @ Dirk-eddelbuettel bao gồm cung cấp một nền tảng cho cả R và một trong những giấy tờ có liên quan nhất về độ chính xác số trong tính toán nói chung. This post cung cấp câu trả lời chung chi tiết hơn về SO liên quan đến khoa học máy tính đằng sau vấn đề này.

Để cho thấy nguyên nhân gốc là độ chính xác bằng số, hãy xem xét chuỗi bạn đã tạo. Đầu tiên, in mặc định ra khỏi chuỗi.

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 

Mọi thứ đều ổn. Bây giờ, in ra trình tự của bạn nói với R để hiển thị 16 chữ số.

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 

Bạn thấy rằng '30' được lưu trữ giá trị là 29.999999999999996 và '59' lưu giá trị 58.999999999999993. Bây giờ, nếu chúng ta tạo chuỗi này làm một số nguyên, chúng ta sẽ nhận được kết quả sau.

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 

Hàm cưỡng chế này được dịch 29.99999999999999996 thành 29 và 58.999999999999993 đến 58, về cơ bản thực hiện cắt ngắn. Vì vậy, trong mã của bạn, các phần tử thứ 29 và thứ 58 được tham chiếu hai lần, trong khi các phần tử thứ 30 và thứ 59 không được tham chiếu chút nào.

Trong trường hợp này, đầu ra giống hệt nhau khi sử dụng hàm floor.

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

Một giải pháp cho vấn đề cụ thể của bạn là sử dụng round trước khi truyền chuỗi đến số nguyên.

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

Giải pháp này thực sự hữu ích. Tôi đã nghĩ về độ chính xác số, nhưng tôi không thể tìm ra, làm thế nào để cải thiện điều này. Cảm ơn bạn rất nhiều! – Aga

+0

Điều chắc chắn, các vấn đề về độ chính xác bằng số có thể hiển thị theo những cách không mong muốn. – lmo

1

Sau đây cho thấy chính xác những gì đã xảy ra, bạn sẽ có số 0 ở vị trí 15, 29, ... vì lỗi chính xác của dấu chấm động.

which(seq(0,1, by = 0.01)*100+1 != 1:101) 
# [1] 15 29 30 56 57 58 59 
Các vấn đề liên quan