MATLAB bug with absolute value and conditional statement [duplicate] - matlab

This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Is floating point math broken?
(31 answers)
Closed 7 months ago.
While learning MATLAB, I came across a strange problem with my code. I am trying to receive a number as user input and determine whether the inputted number is in the desired range of 5.4±0.1. As you can see below, I took absolute value of the difference between input and 5.4 and checked if it is less than or equal to 0.1. By the code, any number between 5.3 and 5.5 should output "Part is good," but strangely, it doesn't work for the lower bound, 5.3. Every number between 5.3 and 5.5 works except for 5.3, and even 5.5 (the upper bound) works well. I am wondering if there is something with MATLAB that I am not aware of yet. Thank you!
part = input("Enter the length of a part"); %user input (height)
if (part<0) %if input is a negative number
error("Illegal input"); %error message
elseif (abs(part-5.4) <= 0.1) %if input is 5.4+-0.1
disp("Part is good"); %display 'part is good'
else % if not
disp("Part is not good"); %display 'part is bad'
end

First, none of the numbers you are dealing with except 5.5 can be represented exactly in IEEE double precision floating point binary. So you cannot rely on these edge cases to work out exactly as if they were represented exactly in floating point decimal because they aren't. To see this, here are the exact conversions of the underlying floating point binary bit patterns to decimal which show why one edge calculation works and the other doesn't. Bottom line is you need to use tolerances (e.g., something slightly bigger than 0.1) or do your calculations differently if you want your edge cases to work as expected in decimal. This isn't a MATLAB bug ... it is simply how floating point binary calculations work. Any language that uses IEEE floating point in the background will have the same issues that must be accounted for by the programmer when writing code.
A more detailed discussion can be found here: Why is 24.0000 not equal to 24.0000 in MATLAB?

Related

matlab floating number accuracy 2^(-45)

I have two pair of numbers (155.11 , 155.35) and (154.95 , 155.19), their differences are both 0.24. In matlab if I calculate
(155.11 - 155.35) - (154.95 - 155.19), the matlab will output 2.8422e-14,which is 2^(-45). I know this is an issue of machine resolution on floating number representation, but was curious on the detail, why it is this value? what is special on 45?
eps(155.11) is 2.8422e-14. The rounding already happens in the original numbers you enter.

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.

Matlab precision [duplicate]

This question already has answers here:
Why is 24.0000 not equal to 24.0000 in MATLAB?
(6 answers)
Closed 7 years ago.
I have a question about the precision in Matlab. I searched the questions here and they mention that there are precision problems when using very large or very small numbers and other posts looking at the comparison of numbers. My case is a bit different
I do not have that, my numbers have only 4 decimal places and I want them to add up to one.
Example:
Initial data:
aeb =
0.231215677537590 0.470472652172102 0.203009018534716
0.087759104877338 0.007588684370711
Then I rounded it to get 4 decimals:
aeb = round(aeb*10000)/10000
0.231200000000000 0.470500000000000 0.203000000000000
0.087800000000000 0.007600000000000
Then I identify the largest number and replace it by the difference with one
[~, idx]=max(aeb);
aeb(idx)=0;
aeb(idx)= 1 - sum(aeb);
But when I then do:
1 - sum(aeb)
1.110223024625157e-16
Does anyone know how I can make them add to one ? I just want 3-5 decimal places.
Their sum is within machine epsilon of the number one. The short answer is that any difference that small is indistinguishable from zero.
A practical point to be aware of....
In a lot of computing contexts, you don't want to test for equality, you want to test if the difference is within a certain tolerance. Eg.
abs(x - y) < tol

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 floor bug? [duplicate]

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