Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab floor bug? [duplicate]

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.

like image 653
Boern Avatar asked Dec 01 '25 02:12

Boern


2 Answers

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

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.

like image 32
Cavaz Avatar answered Dec 02 '25 16:12

Cavaz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!