Unexpected result for arithmetic operation
1 view (last 30 days)
Show older comments
Karthik Nagarajan
on 17 Oct 2018
Commented: Walter Roberson
on 17 Oct 2018
Dear all,
I am having some difficulty with what appears to be a bug. Consider the following simple code:
clear;clc;clf;
td=[0.01 0.20:0.20:1.0];
tbinw=0.05;
ibt=ceil(td./tbinw);
tdc=ibt.*tbinw-(tbinw/2.0);
When this is executed, the result for the vector tdc is
tdc =
0.0250 0.1750 0.3750 0.6250 0.7750 0.9750
However, when I test whether the 2nd element of tdc is 0.175, the result is false. Apparently, tdc(2)-0.175 = 2.7756e-17. However, this precision problem does not arise for any of the other elements in tdc.I am wondering why this is the case. This behaviour leads to an error in a subsequent part of my code. I am using a student version of Matlab R2013a.
3 Comments
Philip Borghesani
on 17 Oct 2018
Point of discussion here. Do you think matlab code adviser should warn for any code that uses an inexact floating point increment value for a range? I have made the suggestion in the past but have not pushed it.
Walter Roberson
on 17 Oct 2018
Philip,
My suspicion is that it would be more trouble to people than it is worth to warn about that.
In some development environments, the organizational standards are that there can be no mlint warnings in code. Adding a warning for this could potentially require that quite a bit of code be rewritten. But MATLAB does not really provide any convenient function that might do any better. It is also not clear what "better" would even mean for this.
I can see one potential meaning: MATLAB could provide a "decimal colon" operator. For the sake of discussion I will denote it as ! . The working would be that in the form A!B!C where A and B and C are written as literal decimal constants, that A+k*B for integer k, evaluated in decimal, would exactly equal to what you would get if you had written that value literally -- at least unless not possible due to loss of precision.
Example:
T = .01!.17!2
would be such that
T - [0.01 0.18 0.35 0.52 0.69 0.86 1.03 1.2 1.37 1.54 1.71 1.88]
would be all exactly 0
Now, perhaps this would work out as finding the maximum number of decimal places in the literal constants A and B and effectively multiplying through the constants before evaluation and dividing the result by 10 to the appropriate power, like
T = (round(.01*10^2):round(0.17*10^2):round(2*10^2))/10^2
That worked out in my small test, but one thing I do not know is whether it is guaranteed that for any literal decimal value of the form A.B..Z if that will be bitwise identical to AB..Z/10^(length(B..Z)) . I have not found any exceptions in my tests; e.g., 0.814723686393179 - 814723686393179/10^15 is 0 but that is not the same as a guarantee.
Plausibly someone could write a function for this that worked on character vectors or string values, like
decimalcolon('.01', '.17', '2')
but if Mathworks were going to be adding a mlint warning then it would be better if there were a hook in the editor that could rewrite code such as .01:.17:2 to something suitable.
I do not at the moment have good ideas as to what the meaning of such an operator should be if the operands are expressed in numeric form but are not constants. For example,
dt = 0.17;
T = .01 ! dx ! 2
It would be unlikely that the user would be expecting that to be the same as
T = .01 ! 0.1700000000000000122124532708767219446599483489990234375 ! 2
Accepted Answer
More Answers (0)
See Also
Categories
Find more on Logical 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!