Discussion:
[R] why the base::round(0.015, 2) returns 0.02?
Philipp Upravitelev
2018-11-28 13:49:42 UTC
Permalink
Dear colleagues,
could you help me with the function base::round()? I can't understand how
it works.

For example, when I want to round 0.015 to the second digit, base::round()
returns 0.02.
sprintf('%.20f', 0.015)
[1] "0.01499999999999999944"
0.015 == 0.01499999999999999944
[1] TRUE
round(0.015, 2)
[1] 0.02

Therefore, according to the arithmetic rules, rounded 0.014 to the second
digit is 0.01. Also, the round() function in other programming languages
(Python, Java) returns 0.01. It is a bit counterintuitive but
mathematically correct.

I'll be very pleased if you could help me to figure out why the
base::round(0.015, 2) returns 0.02 and what is the purpose of this feature.

Best regards,
Philipp Upravitelev

[[alternative HTML version deleted]]

______________________________________________
R-***@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.
Rui Barradas
2018-11-28 17:55:21 UTC
Permalink
Hello,

Your assumption that you can sprintf with 20 digits of precision is
wrong, you only have 16 decimal digits. And

sprintf('%.16f', 0.015)
#[1] "0.0150000000000000"

0.015 == 0.0150000000000000
#[1] TRUE

This rounds to the nearest even number, 0.02 (IEEE-754).

Hope this helps,

Rui Barradas
Post by Philipp Upravitelev
Dear colleagues,
could you help me with the function base::round()? I can't understand how
it works.
For example, when I want to round 0.015 to the second digit, base::round()
returns 0.02.
sprintf('%.20f', 0.015)
[1] "0.01499999999999999944"
0.015 == 0.01499999999999999944
[1] TRUE
round(0.015, 2)
[1] 0.02
Therefore, according to the arithmetic rules, rounded 0.014 to the second
digit is 0.01. Also, the round() function in other programming languages
(Python, Java) returns 0.01. It is a bit counterintuitive but
mathematically correct.
I'll be very pleased if you could help me to figure out why the
base::round(0.015, 2) returns 0.02 and what is the purpose of this feature.
Best regards,
Philipp Upravitelev
[[alternative HTML version deleted]]
______________________________________________
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.
______________________________________________
R-***@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.
Duncan Murdoch
2018-11-28 18:14:27 UTC
Permalink
Post by Philipp Upravitelev
Dear colleagues,
could you help me with the function base::round()? I can't understand how
it works.
For example, when I want to round 0.015 to the second digit, base::round()
returns 0.02.
sprintf('%.20f', 0.015)
[1] "0.01499999999999999944"
0.015 == 0.01499999999999999944
[1] TRUE
round(0.015, 2)
[1] 0.02
This calculation is informative:

100*0.015 - 1.5

which gives 0 on my system. So even though 0.015 isn't exactly
representable, when you multiply by 100, you get the exactly correct
result. Then the apparent rule for round(x, 2) is: multiply by 100,
round to an integer, divide by 100.

Duncan Murdoch
Post by Philipp Upravitelev
Therefore, according to the arithmetic rules, rounded 0.014 to the second
digit is 0.01. Also, the round() function in other programming languages
(Python, Java) returns 0.01. It is a bit counterintuitive but
mathematically correct.
I'll be very pleased if you could help me to figure out why the
base::round(0.015, 2) returns 0.02 and what is the purpose of this feature.
Best regards,
Philipp Upravitelev
[[alternative HTML version deleted]]
______________________________________________
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.
______________________________________________
R-***@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.
Richard M. Heiberger
2018-11-28 18:32:19 UTC
Permalink
interesting. this looks like an OS problem, since ?round says
‘round’ rounds the values in its first argument to the specified
number of decimal places (default 0). See ‘Details’ about “round
to even” when rounding off a 5.
Details
Note that for rounding off a 5, the IEC 60559 standard (see also
‘IEEE 754’) is expected to be used, ‘_go to the even digit_’.
Therefore ‘round(0.5)’ is ‘0’ and ‘round(-1.5)’ is ‘-2’. However,
this is dependent on OS services and on representation error
(since e.g. ‘0.15’ is not represented exactly, the rounding rule
applies to the represented number and not to the printed number,
and so ‘round(0.15, 1)’ could be either ‘0.1’ or ‘0.2’).

.015 is right on the boundary. When we look at the internal
representation with Rmpfr,
we see a string of 9s. the 44 at the end is just noise. It looks
like the string of 99 is increased to 100
before rounding.
When we increase the precision from the default double precision
(precBits=53) to precBits=55, we
get the anticipated behavior.
library(Rmpfr)
round(.015, 2)
[1] 0.02
getPrec(.015)
[1] 53
mpfr(0.015, precBits=53)
1 'mpfr' number of precision 53 bits
[1] 0.015
formatDec(mpfr(0.015, precBits=53))
[1] 0.014999999999999999
round(0.014999999999999999, 2)
[1] 0.02
round(0.014999999999999998, 2)
[1] 0.01
round(mpfr(0.015, precBits=54), 2)
1 'mpfr' number of precision 54 bits
[1] 0.02
round(mpfr(0.015, precBits=55), 2)
1 'mpfr' number of precision 55 bits
[1] 0.01
formatDec(mpfr(0.015, precBits=53))
[1] 0.014999999999999999
formatDec(mpfr(0.015, precBits=54))
[1] 0.0149999999999999994
formatDec(mpfr(0.015, precBits=55))
[1] 0.0149999999999999994
roundMpfr(mpfr(0.014999999999999999, precBits=53), 53)
1 'mpfr' number of precision 53 bits
[1] 0.015
roundMpfr(mpfr(0.014999999999999999, precBits=53), 54)
1 'mpfr' number of precision 54 bits
[1] 0.014999999999999999
roundMpfr(mpfr(0.014999999999999999, precBits=53), 55)
1 'mpfr' number of precision 55 bits
[1] 0.014999999999999999
1
formatHex(mpfr(0.015, precBits=53)*100)
[1] +0x1.8000000000000p+0
formatHex(mpfr(0.015, precBits=54)*100)
[1] +0x1.80000000000000p+0
formatHex(mpfr(0.015, precBits=55)*100)
[1] +0x1.7ffffffffffffcp+0
formatHex(mpfr(0.015, precBits=53))
[1] +0x1.eb851eb851eb8p-7
formatHex(mpfr(0.015, precBits=54))
[1] +0x1.eb851eb851eb80p-7
formatHex(mpfr(0.015, precBits=55))
[1] +0x1.eb851eb851eb80p-7
round(mpfr(0.015, precBits=53), 2)
1 'mpfr' number of precision 53 bits
[1] 0.02
round(mpfr(0.015, precBits=54), 2)
1 'mpfr' number of precision 54 bits
[1] 0.02
round(mpfr(0.015, precBits=55), 2)
1 'mpfr' number of precision 55 bits
[1] 0.01
On Wed, Nov 28, 2018 at 12:31 PM Philipp Upravitelev
Dear colleagues,
could you help me with the function base::round()? I can't understand how
it works.
For example, when I want to round 0.015 to the second digit, base::round()
returns 0.02.
sprintf('%.20f', 0.015)
[1] "0.01499999999999999944"
0.015 == 0.01499999999999999944
[1] TRUE
round(0.015, 2)
[1] 0.02
Therefore, according to the arithmetic rules, rounded 0.014 to the second
digit is 0.01. Also, the round() function in other programming languages
(Python, Java) returns 0.01. It is a bit counterintuitive but
mathematically correct.
I'll be very pleased if you could help me to figure out why the
base::round(0.015, 2) returns 0.02 and what is the purpose of this feature.
Best regards,
Philipp Upravitelev
[[alternative HTML version deleted]]
______________________________________________
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.
______________________________________________
R-***@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.
Loading...