Unexpected result for arithmetic operation

3 次查看(过去 30 天)
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 个评论
Philip Borghesani
Philip Borghesani 2018-10-17
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
Walter Roberson 2018-10-17
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

请先登录,再进行评论。

采纳的回答

Karthik Nagarajan
Karthik Nagarajan 2018-10-17
编辑:Jan 2018-10-17

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Creating and Concatenating Matrices 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by