# second condition never gets executed - elseif (temp == 13.2) tried to run in 13b, 15b online edittors as well, any explanations or its a bug?

2 Ansichten (letzte 30 Tage)
rohit kumar Gupta am 20 Feb. 2018
Beantwortet: John BG am 24 Feb. 2018
for temp=0.0:0.01:20
if (temp == 13.19)
disp(temp);
elseif (temp == 13.2)
disp(temp);
elseif (temp == 13.21)
disp(temp);
end
end
##### 1 KommentarKeine anzeigenKeine ausblenden
Stephen23 am 20 Feb. 2018

Melden Sie sich an, um zu kommentieren.

### Akzeptierte Antwort

Jan am 20 Feb. 2018
Bearbeitet: Jan am 20 Feb. 2018
This is not a bug, but the expected behavior of IEEE754 floating point values. See FAQ: Why is 0.3-0.2 not 0.1?
Matlab uses IEEE754 doubles, which are store in binary form internally. There is no exact conversion between binary and decimal numbers, if they are stores with a limited precision. One consequence is the rounding effect when numbers are added:
(0.1 + 0.1 + 0.1) - 0.3 % Not 0.0, but in the magnitude of eps
any((0.0:0.1:1.0) == 0.3) % FALSE
The solution is to use an interval, e.g.:
elseif abs(temp - 13.2) < 10 * eps(13.2)
disp(temp);
The limits of the interval depend on the specific problem.
Welcome to the world of numerics with limited precision.
##### 0 Kommentare-1 ältere Kommentare anzeigen-1 ältere Kommentare ausblenden

Melden Sie sich an, um zu kommentieren.

### Weitere Antworten (3)

Jos (10584) am 20 Feb. 2018
Welcome to the world of computers where it is tricky to compare floating point numbers. Take a look at the answer here: https://uk.mathworks.com/matlabcentral/answers/57444-faq-why-is-0-3-0-2-0-1-not-equal-to-zero
A better condition check is to use some tolerance
if abs(temp-13.21)<0.001
##### 0 Kommentare-1 ältere Kommentare anzeigen-1 ältere Kommentare ausblenden

Melden Sie sich an, um zu kommentieren.

Steven Lord am 20 Feb. 2018
Avoid using == to perform exact, down-to-the-last-bit comparisons between floating point numbers. Compare using a tolerance instead, or find a way to rewrite the comparison to avoid potential floating point issues.
for temp=0:2000 % Multiplied the temp variable by 100 so it takes on only integer values
if (temp == 1319)
disp(temp/100);
elseif (temp == 1320)
disp(temp/100);
elseif (temp == 1321)
disp(temp/100);
end
end
Or since you want to know if temp is one of a specific set of numbers, if you're using release R2015a or later you can use the ismembertol function:
for temp=0.0:0.01:20
if ismembertol(temp, [13.19 13.2 13.21], 1e-6)
disp(temp);
end
end
##### 0 Kommentare-1 ältere Kommentare anzeigen-1 ältere Kommentare ausblenden

Melden Sie sich an, um zu kommentieren.

John BG am 24 Feb. 2018
Hi Rohit Kumar Gupta
As mentioned by the previous contributors, when using a float for this particular variable data range,
it's like using a CHEP pallet (1mx1.2m) in the warehouse
to send to store a couple of fish fingers boxes (very very small)
so it's not really efficient.
1.
One way around the 'universe' of float is to use a step:
clear all;clc;close all
temp_step=.01;
temp=[0.0:temp_step:20];
ntemp=[1:1:20/temp_step+1];
target1=13.91;
target2=13.20;
target3=13.21;
ntarget1=find(temp==target1);
ntarget2=find(temp==target2);
ntarget3=find(temp==target3);
for k=ntemp
if (k == ntarget1) disp(temp(k)); end;
if (k == ntarget2) disp(temp(k)); end;
if (k == ntarget3) disp(temp(k)); end;
end
13.199999999999999
13.210000000000001
13.910000000000000
MATLAB dully places the data you supply in the most significant digits of the float variables, but for the remaining digits that you have not defined?
MATLAB kind of very politely and implicitly says 'be my guest' and takes what from the machine point of view is a reasonable guess,
yet it may not be what you expect as answer.
2.
Types doubles and floats a great data formats, but for your question there's a better and obvious approach,
Use the right container:
Zero the resolution of the container used to the smallest tolerance required
this way, by including the tolerance in the step, we avoid the inherent problems that arise from using way too big containers for way to small data loads.
temp=uint32(temp/temp_step)
target1=13.91/temp_step;
target2=13.20/temp_step;
target3=13.21/temp_step;
ntarget1=find(temp==target1);
ntarget2=find(temp==target2);
ntarget3=find(temp==target3);
for k=ntemp
if (k == ntarget1) disp(double(temp(k))*temp_step); end;
if (k == ntarget2) disp(double(temp(k))*temp_step); end;
if (k == ntarget3) disp(double(temp(k))*temp_step); end;
end
13.200000000000001
13.210000000000001
13.910000000000000
3.
there's still a really tiny residue 1e-15.
If you want to really remove any trace below the 2nd decimal, we should use characters and present the results as
'13.20'
'13.21'
'13.91'
If you are interested to proceed this way please me know.
.
Rohit
thanks in advance for time and attention
John BG
##### 0 Kommentare-1 ältere Kommentare anzeigen-1 ältere Kommentare ausblenden

Melden Sie sich an, um zu kommentieren.

### Kategorien

Find more on Get Started with MATLAB in Help Center and File Exchange

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!