3

R by default uses round half to even on the round() function. But it not seems to be always true when rounding to a defined number of decimal places:

# R code
round(1.225,2)
#[1] 1.23
round(1.2225,3)
#[1] 1.222
round(1.22225,4)
#[1] 1.2223
round(1.222225,5)
#[1] 1.22222

Comparing to python, using the decimal module:

# Python code
import decimal
a = decimal.Decimal("1.225")
b = decimal.Decimal("1.2225")
c = decimal.Decimal("1.22225")
d = decimal.Decimal("1.222225")

a.quantize(decimal.Decimal('1.00'), decimal.ROUND_HALF_EVEN)
#Decimal('1.22')
b.quantize(decimal.Decimal('1.000'), decimal.ROUND_HALF_EVEN)
#Decimal('1.222')
c.quantize(decimal.Decimal('1.0000'), decimal.ROUND_HALF_EVEN)
#Decimal('1.2222')
d.quantize(decimal.Decimal('1.00000'), decimal.ROUND_HALF_EVEN)
#Decimal('1.22222')

From python decimal library docs, about quantize function:

Return a value equal to the first operand after rounding and having the exponent of the second operand.

I'm not sure if I'm right, but looks like the python result is correct.

Question:

Which one is correct, and how to achieve the correct results using the two languages?

art
  • 181
  • 1
  • 9

1 Answers1

7

The problem is the finite precision of floating point values:

>>> '%.18f' % 1.225
'1.225000000000000089'
>>> '%.18f' % 1.2225
'1.222499999999999920'
>>> '%.18f' % 1.22225
'1.222250000000000059'
>>> '%.18f' % 1.222225
'1.222224999999999895'

Pythons Decimal-class is exact in this sense.

Daniel
  • 42,087
  • 4
  • 55
  • 81
  • 1
    To get around this "effect" in `R`, try using `Rmpfr` (or just recognize that it's what happens in any binary representation of floats and live with it :-) ) – Carl Witthoft Nov 16 '14 at 22:35
  • Hi Carl, I'm trying using the `Rmpfr`, but can't figure how to achieve the desired results. See the updates on my question. – art Nov 17 '14 at 18:52
  • 1
    @art Since you already have accepted this answer, and Carl is just a commenter not the answerer, you should ask a new question rather than modifying your question so that the answer you accepted is no longer adequate. – Gregor Thomas Nov 17 '14 at 18:56