Problem with Greater Than and addition?
3 views (last 30 days)
Show older comments
I haven't checked this in other versions, but in Matlab 2015a, or 2014b, or 2014a, try the following:
myVar = 255.22;
myVar2 = myVar + 1;
while (myVar2 - myVar) > 1
disp('Why does this run forever?')
myVar2 = myVar + 1;
end
The above is my problem, boiled down to the least amount of code possible. I'm trying to evaluate some test data and apply a ramp-limiting algorithm. The number that I get back is the number from my sensor. The particular value I'm using here is an actual sensor reading that causes a problem with the algorithm.
If myVar2 is defined to be myVar + 1, then how can myVar2 - myVar ever be greater than one??
There are other values that cause this glitch, at different levels of precision (for example, 63.211666666666666 also causes the problem), but the number above, 255.22, seems to be the one of the most confounding. It's a normal-looking number that doesn't have an excessive number of decimal values. I don't know what to do.
63.460000000000001 is another example. I had initially thought that maybe there were too many digits after the decimal, and while it's extremely frustrating that MATLAB can't handle that, I thought maybe I could round or truncate the number to something that works better. This is actually the current workaround, but it is still not correct because it still doesn't handle 255.22 or any of the otherwise normal-looking numbers below, and this is devastating my project.
Some more innocuous-looking numbers that Matlab can't seem to handle are:
255.6575
255.345
511.94
127.675
255.965
511.1275
255.84
255.845
I could rant, but I won't. I'll just leave this sample set of numbers here and hope someone knows how to fix this. At this point, given that a number like 511.94 fails this test, rounding or truncating is not an acceptable answer.
:EDIT:
Roger Stafford posted below that I have to allow a "tiny margin" to account for the fact that Matlab does binary math and not decimal math. This comment brings up a few more questions:
- What is the exact value of the "tiny margin" that needs to be allowed for? I'm not really at liberty to discuss the particulars of the project, but digits after the decimals matter (especially in a number like 255.22). I'm using a commercial Matlab license on a commercial project and do not want to truncate without justification.
- How should the "tiny margin" be used? I tried adding "myVar = myVar (+/-) 0.01;" before the myVar2 assignment in the while loop above, and wound up with a range of numbers from 255 to 256 that all failed because adding 0.01 wound up actually giving a number like 255.22999999999999.
- How do I tell, in advance, when this is going to be an issue? 255.2 doesn't have this problem, 255.222 doesn't have this problem, 255.2222 doesn't have this problem - only 255.22 does.
- Is there a way to force decimal math (instead of binary math) and skirt the whole problem?
2 Comments
Geoff Hayes
on 5 Jan 2016
Chuck - as Roger indicated in his answer, try manipulating your while condition to compensate for the rounding error. For example,
while (myVar2 - myVar) > 1+200*eps
or
while (myVar2 - myVar) > 1+eps('single')
Stephen23
on 6 Jan 2016
Edited: Stephen23
on 6 Jan 2016
- The required tolerance depends on the magnitude of the values being used, and the requirements of the project. Double type numerics can have values covering over more than 600 orders of magnitude: there is no one tolerance value that will suit all of these values, but the precision is fixed (between 15 and 17 digits for double). Thus you need to select a tolerance that suits your project.
- Read the links in my comment below.
- This is easy: you need to take into account the floating point precision whenever you use floating point values. In practice this means any values with decimal digits (i.e. non integer).
- Build a decimal computer.
Accepted Answer
Roger Stafford
on 5 Jan 2016
You need to be aware that your computer does its computation in binary digits not decimal digits. Hence it cannot represent 255.22 exactly and uses the binary fraction nearest that value. When you add 1, the resulting difference may not be a precise 1. Therefore you must allow a tiny margin for rounding error in your 'while' condition. This issue is a very old one on this forum.
4 Comments
Roger Stafford
on 6 Jan 2016
Edited: Roger Stafford
on 6 Jan 2016
Chuck - From earliest times there has been a preference in the design of digital computers for doing arithmetic with binary digits rather than decimal digits, since the logic involved is considerably simpler. For this reason the computer you are using undoubtedly has build-in logic for performing binary floating point computations in accordance with the well-known IEEE 754 standard set up in 1985. This is a fact of the hardware you are using, not something devised by Mathworks. There is no provision for directly switching to a decimal mode in such hardware. It can only be done by the relatively inefficient method of using decimal strings as is done in the Symbolic Toolbox.
Geoff has shown you how you can provide that "tiny" error tolerance in your 'while' instruction which I mentioned earlier with the use of the 'eps' function. It is much better in my opinion to use such methods as this to provide for the eccentricities of binary arithmetic than having to resort to decimal strings.
Stephen23
on 6 Jan 2016
Edited: Stephen23
on 6 Jan 2016
Indeed, MATLAB has not done anything wrong. Users who expect binary floating-point calculations to give exact symbolic results are going to be in for some uncomfortable surprises when they start programming, but this is not MATLAB's fault. Standard numeric data types double and single are used in MATLAB and many other languages, are supported by lots of computer hardware, and their behaviors are well documented. Perhaps the OP might like to actually take the opportunity to learn something:
And some external links on this topic:
More Answers (0)
See Also
Categories
Find more on Characters and Strings in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!