[R] Interesting quirk with fractions and rounding

21 views
Skip to first unread message

Paul Johnson

unread,
Apr 20, 2017, 5:56:39 PM4/20/17
to R-help
Hello, R friends

My student unearthed this quirk that might interest you.

I wondered if this might be a bug in the R interpreter. If not a bug,
it certainly stands as a good example of the dangers of floating point
numbers in computing.

What do you think?

> 100*(23/40)
[1] 57.5
> (100*23)/40
[1] 57.5
> round(100*(23/40))
[1] 57
> round((100*23)/40)
[1] 58

The result in the 2 rounds should be the same, I think. Clearly some
digital number devil is at work. I *guess* that when you put in whole
numbers and group them like this (100*23), the interpreter does
integer math, but if you group (23/40), you force a fractional
division and a floating point number. The results from the first 2
calculations are not actually 57.5, they just appear that way.

Before you close the books, look at this:

> aa <- 100*(23/40)
> bb <- (100*23)/40
> all.equal(aa,bb)
[1] TRUE
> round(aa)
[1] 57
> round(bb)
[1] 58

I'm putting this one in my collection of "difficult to understand"
numerical calculations.

If you have seen this before, I'm sorry to waste your time.

pj
--
Paul E. Johnson http://pj.freefaculty.org
Director, Center for Research Methods and Data Analysis http://crmda.ku.edu

To write to me directly, please address me at pauljohn at ku.edu.

______________________________________________
R-h...@r-project.org mailing list -- To UNSUBSCRIBE and more, see
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Nordlund, Dan (DSHS/RDA)

unread,
Apr 20, 2017, 6:20:30 PM4/20/17
to Paul Johnson, R-help
This is FAQ 7.31. It is not a bug, it is the unavoidable problem of accurately representing floating point numbers with a finite number of bits of precision. Look at the following:

> a <- 100*(23/40)
> b <- (100*23)/40
> print(a,digits=20)
[1] 57.499999999999993
> print(b,digits=20)
[1] 57.5
>

Your example with all.equal evaluates TRUE because all.equal uses a 'fuzz factor'. From the all.equal man page

"all.equal(x, y) is a utility to compare R objects x and y testing 'near equality'."


Hope this is helpful,

Dan

Daniel Nordlund, PhD
Research and Data Analysis Division
Services & Enterprise Support Administration
Washington State Department of Social and Health Services

Michael Hannon

unread,
Apr 20, 2017, 6:35:16 PM4/20/17
to Nordlund, Dan (DSHS/RDA), R-help
I might add that things that *look* like integers in R are not really
integers, unless you explicitly label them as such:

> str(20)
num 20

> str(20.5)
num 20.5

> str(20L)
int 20
>

I think that Python 2 will do integer arithmetic on things that look
like integers:

$ python2
.
.
.
>>> 30 / 20
1
>>>

But that behavior has changed in Python 3:

$ python3
.
.
.
>>> 30 / 20
1.5
>>>

-- Mike
Reply all
Reply to author
Forward
0 new messages