6

I am doing a simple operation of multiplying a decimal number and converting it to integer but the result seems to be different than expected. Apologies if this is discussed else where, I am not able to find any straight forward answers to this

> as.integer(1190.60 * 100)
[1] 119059

EDIT: So, I have to convert that to character and then do as.integer to get what is expected

> temp <- 1190.60
> temp2 <- 1190.60 * 100
> class(temp)
[1] "numeric"
> class(temp2)
[1] "numeric"
> as.character(temp2)
[1] "119060"
> as.integer(temp2)
[1] 119059
> as.integer(as.character(temp2))
[1] 119060

EDIT2: According to the comments, thanks @andrey-shabalin

> temp2
[1] 119060
> as.integer(temp2)
[1] 119059
> as.integer(round(temp2))
[1] 119060

EDIT3: As mentioned in the comments the question is related to behaviour of as.integer and not about floating calculations

pshirishreddy
  • 746
  • 6
  • 20
  • So I have to convert that to character first and then use as.integer – pshirishreddy Apr 19 '17 at 13:24
  • What is the reason you need it as integer? – Dason Apr 19 '17 at 13:27
  • 6
    I suggest rounding the number first, not converting to character. `as.integer(round(temp))` – Andrey Shabalin Apr 19 '17 at 13:27
  • 1
    This is a floating-point accuracy issue: `temp2-119060 = -1.455192e-11` – Ben Bolker Apr 19 '17 at 13:28
  • 3
    close as duplicate of http://stackoverflow.com/questions/9508518/why-are-these-numbers-not-equal ? – Ben Bolker Apr 19 '17 at 13:29
  • 1
    @BenBolker thought about that, but that question doesn't really talk about the behaviour of `as.integer`, which seems to be the core question here. Obviously this is floating point stuff, but the answer here is the rounding behaviour of `as.integer`. – Joris Meys Apr 19 '17 at 13:37
  • 1
    From the documentation of `as.integer()`: *Non-integral numeric values are truncated towards zero * – jogo Apr 19 '17 at 13:39
  • 1
    Possible duplicate of [Why are these numbers not equal?](http://stackoverflow.com/questions/9508518/why-are-these-numbers-not-equal) – jogo Apr 19 '17 at 13:40

1 Answers1

5

The answer to this is "floating point error". You can see this easily by checking the following:

> temp <- 1190.60
> temp2 <- 1190.60 * 100
> temp2 - 119060
[1] -1.455192e-11

Due to floating point errors, temp2 isn't exactly 119060 but :

> sprintf("%.20f", temp2)
[1] "119059.99999999998544808477"

If you use as.integer on a float, it works the same way as trunc, i.e. it does round the float in the direction of 0. So in this case that becomes 119059.

If you convert to character using as.character(), R will make sure that it uses maximum 15 significant digits. In this example that would be "119059.999999999". The next digit is another 9, so R will round this to 119060 before conversion. I avoid this in the code above by using sprintf() instead of as.character().

Joris Meys
  • 106,551
  • 31
  • 221
  • 263
  • What about round(), does that follow the same semantics used for as.character() rounding ? – pshirishreddy Apr 19 '17 at 13:36
  • @pshirishreddy how so what about round? round() works as advertised on its help page: it rounds to the nearest integer. So `as.integer(round(temp2))` gives you what you'd expect. – Joris Meys Apr 19 '17 at 13:38