Exact fraction arithmetic without Matlab converting to decimal representation? - matlab

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.

Related

Question about floating-point arithmetic in Matlab

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.

Calculate the variance of an integer vector in MATLAB

I need to calculate the variance of a large vector which is stored as uint8. The MATLAB var function however only accepts double and single types as input. The easiest way to calculate the variance would therefore be
vec = randi(255,1,100,'uint8');
var(single(vec))
This of course gives the correct result. However using single datatype increses the memory usage by a factor of 4. For large vectors (~ 1 million elements) this will quickly fill up the memory.
What I tried: The definition of the variance for a discrete random variable X is
(Source: Wikipedia)
I estimated the p's using the histogram, but then got stuck: To calculate the variance in a vectorized fashion, I would need to convert the x_i's to single or double.
Is there any possibility to calculate the variance without converting the whole vector to single or double?
If you're willing to work with uint16, you can do this, it creates only 3 floating point numbers (var and the 2 means), use Var(X)=Mean(X^2)-Mean(X)^2:
uivec=uint16(vec);
mean(uivec.^2)-mean(uivec)^2
So, not as good as keeping uint8 but still twice better than converting to single. It should work with uint16 because your input is uint8 and (2^8)^2=2^16.
If you want the exact same answer as var, you need to remember that MATLAB uses the unbiased estimator for var (it divides the sum by n-1 instead of n, where n is your number of samples) so you need to do:
n=length(vec);
v=mean(uivec.^2)-mean(uivec)^2*(n/(n-1))
then your v will be exactly equal to var(single(vec)).
No. The value of the variance is going to be a floating point value most likely, so you need to perform floating point operations.
p_i itself is the Probability mass function, so sum(p_i) should be one, therefore each p_i is a floating point number.
In addition, nu, the mean, will probably not be integer neither

Matlab treatment of numerical expression

Why does Matlab display 1.0000 when entering 1-10^(-16) but 1 when entering 1-10^(-17)? Is there any difference in floating point treatment or is anything else? Thanks in advance
Basically, MATLAB can only store 16 significant digits.
MATLAB uses IEEE 754 double-precision floating point numbers, which can represent ~16 decimal digits. In this format, 1-10^-16 is stored as:
0x3fefffffffffffff
The next double after this is:
0x3ff0000000000000
which just so happens to be 1. In other words, it's not possible for MATLAB to represent 1-10^17 exactly, so it rounds it to the nearest number it can represent, which turns out to be 1.

Matlab: reverse of eps? Accuracy on positive weight?

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.

Matlab_Is there a bug in the representation of number e?

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.