Is it ok to have rounding errors when rounding to integers?

Run the following:
round(100000,-5)
In my opinion it should return 100000 exactly, but it returns 100000+eps(100000). Do you think this is a bug, or is it an expected round off error because of floating point arithmetic?

 Accepted Answer

dpb
dpb on 19 Jan 2017
Edited: dpb on 20 Jan 2017
Does appear to be a "quality of implementation" issue. Hadn't ever used it w/ the negative optional argument but looks like does have some artifacts, not clear quite where this one would come from. Since it's builtin function can't see implementation but that's what it looks like happens...altho for this input the "deadahead"
>> fix(100000/1E5)*1E5
ans =
100000
>>
works so not sure what must be going on internally.
Looks to me to be worth a bug report.
A workaround I'm sure you've already thought of is to wrap the call in another round...
>> round(round(100000,-5))
ans =
100000
>>

More Answers (3)

In general, you cannot represent numbers (that have digits to the right of the decimal point) exactly in floating point arithmetic. So when you use round in this form, you are rounding to the 5th decimal place to the right of the decimal point.
The problem is, only you know that the result should be an integer, because it was an integer before the "round" operation.
round(100000,-5) == 100000
ans =
logical
0
sprintf('%0.55f',round(100000,-5))
ans =
100000.0000000000145519152283668518066406250000000000000000000
What happened is round (with a second operand) works by scaling the number, then performing a round, and then scaling back. But it depends on how the code was written internally, and we don't see the code for round.
This works:
x = 100000;
round(x*10^5)/10^5 == x
ans =
logical
1
But this fails:
round(x/10^-5)*10^-5 == x
ans =
logical
0
My guess is that for negative second argument, this is what they do. However, it would be better to do different operations, depending on whether the second argument is positive or negative.

6 Comments

I think you are mistaking round(100000,-5) with round(100000,5). I am rounding to the nearest 100000, i.e. the 5th decimal to the left of the decimal point.
I think John's explanation applies to rounding left of the decimal place as well, e.g.,
>> x=1e5;
>> round(x*1e-5)/1e-5 == x
ans =
0
However, like others have been saying, I do think it's reportable as a bug. There's no reason, except maybe in a GPU implementation, that round() shouldn't pre-check that your input is already an integer. There's similarly no reason that it should do
round(x*scale)/scale
as opposed to
round(round(x*scale)/scale)
in cases like this one where it is a priori knowable that the the output should be an integer.
Sorry. Yes, rounding in either direction can cause numerical problems. It is arguably fixable for at least some cases, so this does not happen.
Seems to me the function description implies that the result for -N should always be integer-valued by being round ed if necessary. The example given surely implies that to my reading, anyways...
Floating point numbers do not have problems representing integer numbers. Of course, when you start doing operations on them, these can introduce inaccuracies (as in this example), but at least in this example I would say that it is because of a bad implementation.
"Floating point numbers do not have problems representing integer numbers." up to the length of the number of digits representable by the chosen precision, of course. That's roughly 15 decimal digits for double.

Sign in to comment.

In my opinion it's a bug that you should report to Mathworks.
It's ironical that round produces a less rounded number than you started with.
I wrote a bug report to Mathworks before posting this question, but they started arguing that it was expected behavior, and I just wanted other opinions. Thanks all.

1 Comment

I'd refer back to the function description in the documentation as to its definition of what is expected output. (If it were my report as I've harped on the issue there is no actual language specification for years, I'd ask what the internal language design document says about it :) )

Sign in to comment.

Products

Tags

Edited:

dpb
on 20 Jan 2017

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!