Matlab floor bug? [duplicate] - matlab

This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 5 years ago.
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.

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.

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

Related

Matlab single to double conversion error [duplicate]

This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 5 years ago.
Does someone know why casting double() on a single precision floating point number in Matlab (R2016a) changes the last digits? Here is an example:
format 'long'
x=3.2530601; %arbitrary single precision number
x_s=single(x);
x_d=double(x_s);
If I look at the classes and values of the variables, I can see the following:
x and x_d are doubles, x_s is single as expected. The values are:
x=3.253060100000000
x_s=3.2530601
x_d=3.253060102462769
Since the number 3.2530601 can be represented as a double or single precision floating point number, I don't understant why x and x_d are not the same. They are further away than x+eps(x). I thought maybe Matlab tries to work out the double precision x_d by rational fraction approximation, but calling rat(x,16) does not give the same result as x_d. I'm clueless. Does anyone know what is happening here?
There are two closely-related questions (In MATLAB, are variables REALLY double-precision by default? and Why is 24.0000 not equal to 24.0000 in MATLAB?), that you should be aware of, but this isn't quite covered fully by either of them...
When you calculate the decimal equivalent for a given significand and exponent of a floating-point value, you can calculate it out to as many decimal places as you want, but any places beyond the floating-point relative accuracy are ultimately of no real value and are typically not even displayed. However, they seem to come into play here when converting a lower-precision number to a higher-precision number.
Let's look at your value for x_s, both as it is displayed normally (only showing significant digits) and how vpa would display it (with an arbitrary number of digits):
>> x_s = single(3.2530601) % Create a single-precision number
x_s =
single
3.2530601
>> eps(x_s) % Floating-point relative accuracy
ans =
single
2.3841858e-07
>> vpa(x_s, 16) % Show 16 digits of precision, way more than the relative accuracy
ans =
3.253060102462769
>> x_d = double(x_s) % Convert to double-precision
x_d =
3.253060102462769
Look at that! The digits from vpa match the digits gotten when converting to double-precision. It would appear that, when converting from a single to a double, MATLAB calculates the decimal equivalent of the lower-precision value out to the number of digits for the higher-precision value, and uses that to initialize it.

63 is not equal to 2^(log(63)/log(2)) in Matlab [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 6 years ago.
Because of the floating point error 2^(log(63)/log(2)) isn't equal to 63. Check the results below:
format long;
>> 2^(log(63)/log(2))
ans =
63.000000000000014
And unfortunatelly i can't use vpa on a logarithm according to the Matlab documents:
Unlike exact symbolic values, double-precision values inherently
contain round-off errors. When you call vpa on a double-precision
input, vpa cannot restore the lost precision, even though it returns
more digits than the double-precision value. However, vpa can
recognize and restore the precision of expressions of the form p/q,
pĪ€/q, (p/q)1/2, 2q, and 10q, where p and q are modest-sized integers.
So how can i solve this issue ? I have very big numbers like 2^200 and i get very big errors.
Edit: I'm not asking why it is happening. I'm asking how to make this work as 100% accurate so this isn't a duplicate.
The best solution so far:
Unfortunatelly the solution that is suggested by #Sardar_Usama isn't always working as intended. Check the results below:
>> sym(2^(log(2251799813685247)/log(2)))
ans =
2251799813685259
On the other hand
>> 2^(log(vpa(2251799813685247))/log(vpa(2)))
ans =
2.2517998136852470000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0*10^0*10^15
is much much more closer to 2251799813685247 = 2^51. It's error is around ~9.491*10^-494 which makes this the best solution so far but there is still some error.
If you cannot use round or vpa, there is a slower way of dealing this, if you have Symbolic Math Toolbox, by creating symbolic numbers . i.e.
a = sym(2^(log(63)/log(2)))
This will give you sym class 63 which you can later convert to double using:
double(a)
This is what you'll get:
>> format long
>> a = sym(2^(log(63)/log(2)))
a =
63
>> double(a)
ans =
63

exponential function with large argument in matlab [duplicate]

This question already has answers here:
How to compute an exponent in matlab without getting inf?
(3 answers)
Closed 7 years ago.
I've got one problem for a longer time and I'd be really grateful if you could help me somehow...
I have a code in MATLAB (version R2012a) where I compute some exponential functions using MATLAB's fuction exp. This means that I have something like this:
y = exp(x);
However, when this "x" is larger than a certain number, the result ("y") is infinity; when "x" is smaller than a certain number, the result is 0. As said on the MathWorks' website:
Numerical exceptions may happen, when the absolute value of the real
part of a floating-point argument x is large. If ℜ(x) < -7.4*10^8,
then exp(x) may return the truncated result 0.0 (protection against
underflow). If ℜ(x) > 7.4*10^8, then exp(x) may return the
floating-point equivalent RD_INF of infinity.
My problem is quite obvious - my "x" are pretty large so I receive infinities and zeros instead of results I need. My question is - how do I get the real results? Thanks in advance for help!
Use vpa with a string input:
>> exp(1000)
ans =
Inf
>> vpa('exp(1000)')
ans =
1.9700711140170469938888793522433*10^434
Note the result of vpa is of class sym.
A variable in any language is stored in a certain amount of bytes in the computer's memory. The more bytes used to hold a variable type, the more precise of a result that variable can hold. If you are using integers, the biggest type uses 64 bytes and is uint64. This is an unsigned integer (meaning it can only be positive) that can range from 0 to 18,446,744,073,709, 551,615. If you need decimals, try using vpa.

Matlab indexing uses floating point numbers?

In short, my question is:
Is a double in Matlab really a double, or is it a class with the additional property to act as an integer?
And here is the context and motivation for the question :)
>> 1:4
ans =
1 2 3 4
>> class(ans)
ans =
double
Just doing this creates a double...
>> 1.00:4.00
ans =
1 2 3 4
>> class(ans)
ans =
double
...as does this, even though it's printed as integers.
The floating point nature of the numbers only shows when greater numerical uncertainty is introduced.
>> acosd(cosd(1:4))
ans =
0.999999999999900 1.999999999999947 3.000000000000045 4.000000000000041
Is a double in Matlab really a double, or is it a class with the additional property to act as an integer?
A vector defined with "integers" (which of course really is doubles), it can be used to index another vector, which is usually a property of integers.
>> A = [9 8 7 6]
A =
9 8 7 6
>> idx = [4 3 2 1]
idx =
4 3 2 1
>> class(idx)
ans =
double
>> A(idx)
ans =
6 7 8 9
I also tried A(acosd(cosd(1:4))) which does not work.
It's just a double, but your command prompt format gives you the most compact view. Specifically,
format short
But you can change it to always display decimals, and lots of them, with
format longEng
There are many other options on the format help page.
Interestingly, you can use non-integer numbers as indexes with the colon operator, but it will warn. I would take this warning seriously as this indexing behavior is odd.
As I mentioned in my comments, the reason it is OK for MATLAB to use doubles for indexing has to do with the largest value of an integer that can be specified without losing precision in MATLAB. Double precision (64-bit) floating point numbers can exactly represent integers up to 2^53 (9,007,199,254,740,992) without losing any accuracy. The maximum array size allowed by MATLAB is far below this number, so there is no risk of indexing errors as a result of floating point precision.
In MATLAB, all numeric literals (i.e. numbers in the text of your program) are interpreted as double-precision. You must cast them explicitly to get any other type. It's worth remembering that IEEE floating point can exactly represent a wide range of integer values, up to FLINTMAX.

two values are seemingly the same, yet matlab says the aren't [duplicate]

This question already has an answer here:
What is -0.0 in matlab?
(1 answer)
Closed 9 years ago.
I cannot explain this. I have two variables having the same value, yet they are not identical. Can anybody tell me what I'm missing here?
>> y
y =
3.4000
>> x
x =
3.4000
>> y==x
ans =
0
>> whos x
Name Size Bytes Class Attributes
x 1x1 8 double
>> whos y
Name Size Bytes Class Attributes
y 1x1 8 double
It's really puzzling for me and I swear it's not a joke.
It's because of floating point precision. Try
format long g
and then look at x and y again. It's better to compare x-y to some small tolerance value rather than doing an equality test on floating point numbers
You're comparing float values, an activity which doesn't work quite how you think in basically any language, due to how floating-point values are handled by computers.
The solution to this is generally to instead test whether the different between the values is less than some small threshold.
See here for a Matlab-related discussion of this.