Why Is Colon Operator Not Equivalent To linspace Command?
35 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Michael Cappello
am 14 Nov. 2024 um 17:47
Beantwortet: Walter Roberson
am 14 Nov. 2024 um 22:04
Why does q not equal zero in the following?
q = isequal(0:.08:50000,linspace(0,50000,625001))
1 Kommentar
Voss
am 14 Nov. 2024 um 20:21
A = 0:0.08:50000;
B = linspace(0,50000,625001);
C = (0:50000*12.5)/12.5;
isequal(A,B)
isequal(A,C)
isequal(B,C)
Antworten (3)
James Tursa
am 14 Nov. 2024 um 18:00
Bearbeitet: James Tursa
am 14 Nov. 2024 um 18:12
The short answer is that the algorithms are different. In the first place, 0.08 cannot be represented exactly in IEEE double precision floating point, so using that as the delta does result in some binary floating point calculation inaccuracies compared to what you might expect looking at the decimal version. E.g., if you read the doc for colon, it doesn't even guarantee that you get the requested end point if the delta is not an integer. On the other hand, the linspace algorithm always gives you the end points. Also, the intermediate points might not match up exactly either, again because of floating point effects based on the different algorithms. E.g.,
a = 0:.08:50000;
b = linspace(0,50000,625001);
numel(a) == numel(b)
max(abs(a-b))
In your case, you happened to get the same number of elements with both methods, but the points generated are not exactly the same because of floating point effects of the different algorithms.
k = find(a ~= b,1,'last')
eps(a(k))
num2hex(a(k))
num2hex(b(k))
And above you can see the max difference is on the order of eps of the largest element that had a difference. I.e., the very last bit of the floating point value. Generally I would prefer linspace over colon in cases like yours so that you have control over the end points being generated.
0 Kommentare
Torsten
am 14 Nov. 2024 um 18:04
Both arrays seem to be generated differently such that floating point issues come into play:
z1 = 0:.08:50000;
z2 = linspace(0,50000,625001);
[~,idx] = find(z1~=z2);
format long
z1(idx)-z2(idx)
0 Kommentare
Walter Roberson
am 14 Nov. 2024 um 22:04
The colon operator is defined to use repeated addition. When the increment does not happen to be an integer multiple of a power of 2, there are round-off error problems. For example, 0.08 is not represented by the rational fraction 8 / 100
fprintf('%.999g\n', 0.08)
those ....1665<etc> accumulate under repeated addition.
The colon operator is not defined as (0:NumberOfValues-1)*Increment+BaseNumber . If it were defined that way, then
for K = 1:inf
would have to generate a vector 1, 2, 3, ... 9223372036854775806 ahead of time and use the elements from that vector. But 9223372036854775806 is 2^63 and it is not possible to generate vectors longer than 2^47-1 even if memory was available.
Of course, potentially MATLAB could have defined that the colon operator in
K=1:1.1:2^40
worked differently than the colon operator in
for K=1:1.1:2^40
but it chose to define them the same way: using repeated addition both ways.
0 Kommentare
Siehe auch
Kategorien
Mehr zu Logical finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!