6

If the following code is executed MATLAB makes a mistake. Can someone verify this?

floor([0.1:0.1:2]/0.01)

So what is the 129 doing here??

ans = 10 20 30 40 50 60 70 80 90 100 110 120 129 140 150 160 170 180 190 200
Andrey Rubshtein
  • 20,795
  • 11
  • 69
  • 104
mmumboss
  • 690
  • 1
  • 5
  • 13

3 Answers3

9

It is a floating point rounding error because of the colon-generated vector.
Like Rasman said, if you do:

floor((0.1:0.1:2 + eps) / 0.01)

There will be no rounding errors.

However, based on how the colon operator works, I suggest that you do the same calculation like this:

floor([(1:20)/10] / 0.01)

[Edit: following Rasman's comment, I will add that the latter approach works for negative values as well, while adding eps sometimes fails]

The bottom line is that it is better using the colon-operator with integer numbers to minimize rounding errors.

Eitan T
  • 32,660
  • 14
  • 72
  • 109
4

It is probably doing a floating point calculation resulting in an inexact value of 129.99999999999999... something instead of 130. and then you floor it to 129.

Markus Mikkolainen
  • 3,397
  • 18
  • 21
4

it's a rounding approximation brought on by the array construction. The solution would be to add eps:

floor([0.1:0.1:2]/0.01+ eps([0.1:0.1:2]/0.01))
Rasman
  • 5,349
  • 1
  • 25
  • 38
  • Thank you, is this a workaround for this specific situation? Or do you recommend this kind of code always in such cases? – mmumboss Jun 07 '12 at 11:36
  • Most of the time I've seen a rounding problem it is because it is off by a single least significant bit (perhaps 2, although I can't recall seeing one. You can be super-safe by adding 2*eps, but for this type of problem it works: `any((floor([0.1:0.1:200]/0.01 + eps([0.1:0.1:200]/0.01))) - (10:10:20000))` – Rasman Jun 07 '12 at 11:42
  • 1
    I take that back, it works while you are in positive territory – Rasman Jun 07 '12 at 11:45
  • @EitanT I completely disagree, you're trying to add a value-specific eps, not some generic number. Use my example and compare: `any((floor([0:0.1:2]/0.01 +eps)) - (0:10:200))` vs `any((floor([0:0.1:2]/0.01 +eps([0:0.1:2]/0.01))) - (0:10:200))` – Rasman Jun 07 '12 at 11:49
  • @Rasman +1 for beating me to the answer with `eps`, and +1 for the comment on the negative values ;) About the second comment, look at what I wrote in my answer, in the first approach. Add the `eps` to the colon-generated vector, _before_ the division. – Eitan T Jun 07 '12 at 11:50