When I compute the following in Matlab
myeps = abs(3*(4/3-1)-1);
format long e
eps_myeps = [eps ; myeps]
The output is as follows:
eps_myeps =
2.220446049250313e-16
2.220446049250313e-16
Why is myeps not 0? Why does this not hold when the base is 3 instead of 2?
Code 4/3 is 4/3 in math. 4/3 is not exactly encodable as a floating point number. Most floating point numbers are dyadic rationals (an integer times some power of 2) and a nearby value is used.*1 Much like we can not write 4/3 exactly in decimal, only 1.3333333 and stop after so many digits.
In this case, The subtraction is expected to be exact as well as the multiplication and final subtraction. Yet the first quotient is not 4/3 and so the final result might not be 0.0.
*1
decimal 1.3333333333333332593184650249895639717578887939453125
hex 0x1.5555555555555
I feel the OP is also searching for an answer for "How could obtain a 0 as an answer", besides
"Why is myeps not 0". So here is the answer. You'll need the Symbolic Math Toolbox for MATLAB.
You can create symbolic numbers by using sym. Symbolic numbers are
exact representations, unlike floating-point numbers.
So if you type 3*(sym(4)/sym(3)-1)-1 into MATLAB (once you got the toolbox), the answer will be exact
0
Just mind the sym(4)/sym(3) part. If you try sym(4/3), MATLAB will get a floating-point first, then try to convert it to symbolic. That will lose precision and not produce 0 as an answer.
Related
So suppose I want to compute 1/9+1/13 in exact fraction form. Since both numbers are rational, an exact result in fraction form is possible. But when I type 1/9+1/13 in Matlab, the result is always a decimal approximation.
How do I obtain exact fractional form?
Matlab is primarily a numeric environment and thus uses floating-point numbers by default. Generally, you'll need to use the Symbolic Math toolbox for something like what you describe. In the case of your example:
sym('1/9')+sym('1/13')
returns 22/117.
Alternatively, you could try the rats (rational fraction approximation) function that works with floating point inputs:
rats(1/9+1/13)
returns the string '22/117'. There's also rat that returns the numerator and denominator as separate floating point outputs.
[n,d] = rat(1/9+1/13)
returns 22 and 117 for n and d, respectively.
Has anyone tried plotting a sine function for large values in MATLAB?
For e.g.:
x = 0:1000:100000;
plot(x,sin(2*pi*x))
I was just wondering why the amplitude is changing for this periodic function? As per what I expect, for any value of x, the function has a period of 2*pi. Why is it not?
Does anyone know? Is there a way to get it right? Also, is this a bug and is it already known?
That's actually not the amplitude changing. That is due to the numerical imprecisions of floating point arithmetic. Bear in mind that you are specifying an integer sequence from 0 to 100000 in steps of 1000. If you recall from trigonometry, sin(n*x*pi) = 0 when x and n are integers, and so theoretically you should be obtaining an output of all zeroes. In your case, n = 2, and x is a number from 0 to 100000 that is a multiple of 1000.
However, this is what I get when I use the above code in your post:
Take a look at the scale of that graph. It's 10^{-11}. Do you know how small that is? As further evidence, here's what the max and min values are of that sequence:
>> min(sin(2*pi*x))
ans =
-7.8397e-11
>> max(sin(2*pi*x))
ans =
2.9190e-11
The values are so small that they might as well be zero. What you are visualizing in the graph is due to numerical imprecision. As I mentioned before, sin(n*x*pi) = 0 when n and x is are integers, under the assumption that we have all of the decimal places of pi available. However, because we only have 64-bits total to represent pi numerically, you will certainly not get the result to be exactly zero. In addition, be advised that the sin function is very likely to be using numerical approximation algorithms (Taylor / MacLaurin series for example), and so that could also contribute to the fact that the result may not be exactly 0.
There are, of course, workarounds, such as using the symbolic mathematics toolbox (see #yoh.lej's answer). In this case, you will get zero, but I won't focus on that here. Your post is questioning the accuracy of the sin function in MATLAB, that works on numeric type inputs. Theoretically with your input into sin, as it is an integer sequence, every value of x should make sin(n*x*pi) = 0.
BTW, this article is good reading. This is what every programmer needs to know about floating point arithmetic and functions: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html. A more simple overview can be found here: http://floating-point-gui.de/
Because what is the exact value of pi?
This apparent error is due to the limit of floating point accuracy. If you really need/want to get around that you can do symbolic computation with matlab, see the difference between:
>> sin(2*pi*10)
ans =
-2.4493e-15
and
>> sin(sym(2*pi*10))
ans =
0
I have been working on finding a parabola with three points by using the determinant method.
The coefficients that are returned are sometimes
-0.0000
What does this mean? Why is there a negative sign and what does it signify?
Try format long g to see more significant digits. The number is probably very slightly negative.
eps returns the distance from 1.0 to the next largest double-precision number, so I can use it to interpret the numbers value on negative weight position. But for very large number with value on high positive weight position, what can I use to interpret?
I mean that I need to have some reference to count out computation noise on numbers obtained on Matlab.
Have you read "What Every Computer Scientist Should Know About Floating-Point Arithmetic"?
It discusses rounding error (what you're calling "computation noise"), the IEEE 754 standard for representation of floating-point numbers, and implementations of floating-point math on computers.
I believe that reading this paper would answer your question, or at least give you more insight into exactly how floating point math works.
Some clarifications to aid your understanding - too big to fit in the comments of #Richante's post:
Firstly, the difference between realmin and eps:
realmin is the smallest normalised floating point number. You can represent smaller numbers in denormalised form.
eps is the smallest increment between distinct numbers. realmin = eps(realmin) * 2^52.
"Normalised" and "denormalised" floating point numbers are explained in the paper linked above.
Secondly, rounding error is no indicator of how much you can "trust" the nth digit of a number.
Take, for example, this:
>> ((0.1+0.1+0.1)^512)/(0.3^512)
ans =
1.0000
We're dividing 0.3^512 by itself, so the answer should be exactly one, right? We should be able to trust every digit up to eps(1).
The error in this calculation is actually 400 * eps:
>> ((0.1+0.1+0.1)^512)/(0.3^512) - 1
ans =
9.4591e-014
>> ans / eps(1)
ans =
426
The calculation error, i.e. the extent to which the nth digit is untrustworthy, is far greater than eps, the floating-point roundoff error in the representation of the answer. Note that we only did six floating-point operations here! You can easily rack up millions of FLOPs to produce one result.
I'll say it one more time: eps() is not an indicator of the error in your calculation. Do not attempt to display : "My result is 1234.567 +/- eps(1234.567)". That is meaningless and deceptive, because it implies your numbers are more precise than they actually are.
eps, the rounding error in the representation of your answer, is only 1 part per billion trillion or so. Your real enemy is the error that accumulates every time you do a floating point operation, and that is what you need to track for a meaningful estimate of the error.
Easier to digest than the paper Li-aung Yip recommends would be the Wikipedia article on machine epsilon. Then read What Every Computer Scientist ...
Your question isn't very well worded, but I think you want something that gives the distance from a number to the next smallest double-precision number? If this is the case, then you can just use:
x = 100;
x + eps(x) %Next largest double-precision number
x - eps(-x) %Next smallest double-precision number
Double-precision numbers have a single sign bit, so counting up from a negative number is the same as counting down from a positive.
Edit:
According to help eps, "For all X, EPS(X) is equal to EPS(ABS(X))." which really confuses me; I can't see how that can be consistent with double having a single sign bit, and values not being equally spaced.
I think There is something wrong in Matlab relative to the number of decimal places used to display the number e.
If put
>> sprintf('%.30f',exp(1))
ans =
2.718281828459045500000000000000
enter code here
I think this is wrong because The number and contains an infinite number of decimal places instead of just the 16 that matlab show in this example.
Does anyone know how I can get better accuracy using Matlab?
Thank you.
No, there is not a bug.
By default, numbers in Matlab are represented by double-precision floating point. These have 52 bits of mantissa, which is approximately equivalent to 16 significant figures. Asking Matlab to print out more decimal places will not magically create more precision.
It's very unlikely you will need more precision than this.
Matlab uses IEEE double precision, so that's as good as you will get for vanilla Matlab.
http://www.mathworks.com/support/solutions/en/data/1-1AGHW/?solution=1-1AGHW suggests getting the Symbolic Math Toolbox, which supports variable precision arithmetic. Or use another tool such as Maple.
Some additional information on double precision and MATLAB.
In the full IEEE system, this spacing is
2- 52. MATLAB calls this quantity eps, which is short for
machine epsilon.
eps = 2^(–52)
Before the IEEE standard, different machines had different
values of eps.
The approximate decimal value of eps is 2.2204 • 10-16.
Either eps/ 2or eps can be called the roundoff level. The
maximum relative error incurred when the result of a single
arithmetic operation is rounded to the nearest floating-point
number is eps/ 2. The maximum relative spacing between
numbers is eps. In either case, you can say that the roundoff
level is about 16 decimal digits.