2

I think I found a bug in Matlab. My only explanation is, that matlab calculates internally with other values than the ones which are displayed:

K>> calc(1,11)

ans =

   4.000000000000000

K>> floor(ans)

ans =

     3

Displayed code is an output from the Matlab console. calc(x,y) is just an array of double values.

Cavaz
  • 2,996
  • 24
  • 38
Boern
  • 7,233
  • 5
  • 55
  • 86
  • how was the value `calc(1,11)` computed/loaded/generated? – tmpearce Sep 26 '12 at 21:46
  • 1
    found [this](http://docs.python.org/tutorial/floatingpoint.html). it's for python but it may give an idea.. – none Sep 26 '12 at 21:50
  • 3
    I suspect if you took calc(1,11) out to its full precision, you would find that it is `3.9999999999999999999999999917825619641` or something of the sort. Floating point math is inexact. Please read any of the other 12986125701 questions on SO showing other errors stemming from FP inaccuracies... – im so confused Sep 26 '12 at 21:57
  • btw yes both those numbers were made by mashing the keyboard. don't quote me on it – im so confused Sep 26 '12 at 21:58
  • computation of this number is really complex...to my knowledge "format long" displays the most information (15 digits). I'm totally familiar with floating point calculations. I would call it a bug, since matlab displays not the number which is used for calculating... – Boern Sep 26 '12 at 22:32
  • 4
    No. it is not a bug, so you are apparently not as familiar as you think with floating point. –  Sep 26 '12 at 22:50
  • 4
    like my old professor of programming 101 said: "Don't you ever dare claiming that C/Matlab/whatheverlanguage is bugged! 99.999% of the cases is your fault / you don't know enough!" – Cavaz Sep 26 '12 at 23:36
  • @LucaCavazzana touché – Boern Oct 15 '13 at 17:48

3 Answers3

8

MATLAB uses the standard IEEE floating point form to store a double.

See that if we subtract off a tiny amount from 4, MATLAB still diplays 4 as the result.

>> format long g
>> 4 - eps(2)
ans =
                         4

In fact, MATLAB stores the number in a binary form. We can see the decimal version of that number as:

>> sprintf('%.55f',4-eps(2))
ans =
3.9999999999999995559107901499373838305473327636718750000

Clearly MATLAB should not display that entire mess of digits, but by rounding the result to 15 digits, we get 4 for the display.

Clearly, the value in calc(1,11) is such a number, represented internally as less than 4 by just a hair too little that it rounds to 4 on display, but it is NOT exactly 4.

NEVER trust the least significant displayed digit of a result in floating point arithmetic.

Edit:

You seem to think that 3.999999999999999 in MATLAB should be less than 4. Logically, this makes sense. But what happens when you supply that number? AH yes, the granularity of a floating point double is larger than that. MATLAB cannot represent it as a number less than 4. It rounds that number UP to EXACTLY 4 internally.

>> sprintf('%.55f',3.9999999999999999)
ans =
4.0000000000000000000000000000000000000000000000000000000
3

What you got was a value really close to but lower than 4, and even with format long Matlab has to round to the 15th digit to display the number. Try this:

format long
asd = 3.9999999999999997 %first not-9 @16th digit

will print 4.000000000000000. Anyone who doesn't know the actual value of asd based on what gets visualized would guess it is at least 4, but running

asd >= 4

gives 0, and so floor(asd) returns 3.

So is a matter of how Matlab rounds the displayed output, the true value stored in the variable is less than 4.

UPDATE:

if you go further with the digits, like 18x9:

>> asd = 3.999999999999999999
asd = 
     4
>> asd == 4
ans =
     1

asd becomes exactly 4! (notice it doesn't display 4.000000000000000 anymore) But that's another story, is no more about rounding the number to have a prettier output, but about how the floating point arithmetic works... Real numbers can be represented up to a certain relative precision: in this case the number you gave is so close to 4 that it becomes 4 itself. Take a look to the Python link posted in the comment by @gokcehan, or here.

Cavaz
  • 2,996
  • 24
  • 38
  • My Problem is, that in this case floor() still returns the expected value. E.g. B = 3.9999999999999999 --> B = 4 --> floor(B) = 4. This doesn't match floor(4.00000......) = 3 – Boern Sep 26 '12 at 23:01
  • that's because you added even more digits, now is about floating point representation. I updated the answer. – Cavaz Sep 26 '12 at 23:23
  • @Batsu Did you mean to write "`floor(asd)` returns `3`"? (nice answer though, +1) – Colin T Bowers Sep 27 '12 at 00:29
1

I won't go over the problem, instead I will offer a solution: Use the single function:

B = single(A) converts the matrix A to single precision, returning that value in B. A can be any numeric object (such as a double). If A is already single precision, single has no effect. Single-precision quantities require less storage than double-precision quantities, but have less precision and a smaller range.

This is only meant to be a fix to this particular issue, so you would do:

K>> calc(1,11)

ans =

   4.000000000000000

K>> floor(single(ans))

ans =

 4
MDMoore313
  • 3,233
  • 1
  • 23
  • 38