0

I wronte some code to correct rounding of percent values with following code (consider comment in the code):

set.seed(123) # set seed to ensure reproducibility
# my original data with which I noticed the odd behavior
x = c(1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 5, 1, 2, 1, 1, 1, 1, 1, 6, 4, 2, 7, 9, 21, 2, 14, 2, 1, 1)
# calculate percent values and make them sum to 100 percent
percent_x = round(x/sum(x)*100,1)
# calculate how many values must be changed to get a sum of 100 percent
i = (sum(percent_x) - 100) * 10 
# take for random values from the vector and index them to subtract .1 each time
# in this case 4
idx = sample(1:length(x), i, replace = F) 
# the number 4 is calculated, however only three values are sampled
percent_x[idx] <- percent_x[idx] - 0.1
sum(percent_x)
# converting i which is 4 to a integer will give back the integer value 3
as.integer(i)

Why behaves r like this and doesn't convert values correctly? Is there an explanation?

R runs on this system:

> sessionInfo()
R version 3.2.1 (2015-06-18)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8 x64 (build 9200)

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252    LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] tools_3.2.1
jnshsrs
  • 337
  • 4
  • 11
  • 3
    This is just floating point arithmetic. You didn't calculate the number 4. You calculated the number `3.9999999999999147`. If you are doing floating point arithmetic on a computer and expect the result to be an integer you'll need to insert an explicit check (round, floor, ceiling, etc) to ensure you get what you want. All programming languages have behavior like this to some degree. – joran Jul 14 '15 at 15:38
  • The above linked duplicate is the "official" canonical reference here, although it focuses more on comparing values than the context in which you happened to encounter this problem. The solution, though, is as I said, to explicitly coerce a floating point result to the desired integer as needed. – joran Jul 14 '15 at 15:44

0 Answers0