Displaying rational numbers in Matlab - matlab

I have two integer numbers m,n which together form a rational number in the form of m/n. Now I just want to display them in Matlab in this rational form.
I can do this by doing
char(sym(m/n))
So, if, e.g. m = 1, n = 2, Matlab will display 1/2. However, if m = 2, n = 4, I am also getting 1/2, whereas I want to get 2/4.
Any way of doing this without recurring to something like
fprintf( '%d/%d', m, n )
Thanks

You can change the display format to rat
>> format rat
>> 2/3
ans =
2/3
otherwise you can call rats function
>> rats(2/3)
ans =
2/3
>> class(ans)
ans =
char
However, in both cases the fractions will be reduced. To avoid that you should create your separate function or introduce it as an anonymous function
>> rat2 = #(m,n) num2str([m n], '%d/%d')
rat2 =
#(m,n)num2str([m,n],'%d/%d')
>> rat2(2,4)
ans =
2/4

Related

Compare symbolic variables

I am trying to compare two symbolic variables (numbers). The whole problem boils down to the following code.
R = vpa(0.555555555555555555555555555);
isAlways(R>R*(1-sym(10^(-10))))
isAlways(R>R*(1-sym(10^(-50))))
Both comparisons should return 1, but the second returns 0.
My solution:
digits(51);
R = vpa(0.555555555555555555555555555);
isAlways(R>R*(1-sym(10^(-10))))
isAlways(R>R*(1-sym(10^(-50))))
Why you encounter this problem
vpa evaluates symbolic inputs with variable-precision floating-point arithmetic (32 significant digits by default)... So what's happening in your case is
>> R = vpa(0.555555555555555555555555555)
R =
0.55555555555555555555555555555556
>> R*(1-sym(10^(-50)))
ans =
0.55555555555555555555555555555556
32 digits are definitely not enough to store the actual value of 1-10^(-50).
How to fix it
Without stressing with vpa() you can declare both R and R * (1 - 10^(-50)) as symbolics (in fact 0.5555555... = 5/9), and compare them:
>> R = str2sym('5/9');
>> X = str2sym('5/9 * (1 - 10^(-50))');
>> isAlways(R > X)
ans =
logical
1

How to find the nearest match for an integer in a given matrix?

I have two matrices. Matrix A(2048,64) and matrix B(10000,64). Values in each element of these matrices is a binary bit, so each row is a representation of a 64-bit binary value, so each row of the matrix has a magnitude between 2^63 and 2^0; Most Significant Bit to Least Significant Bit, respectively.
Problem:
For each row of A I want to find the value in B which is the closest to it in an absolute, numeric sense.
Consider A(i,1:64) being a binary representation of decimal value Xi, and B(j,1:64) a binary representation of decimal value Yj. So at the first step I want to find the best j such that X1 or A(1,1:64) has the closest numeric value to the element at Yj, i.e. abs(X1-Yj) is minimized among all possible values for j.
The below image, brought from here, describes my problem rather well, but the difference is that each of my values are contained in a row of a matrix containing 64 elements.
I tried to convert the 64-bit values to decimal, however dec2bin supports values up to 56-bit only.
You can divide your 64-bit number into two 32-bit pieces, b1 and b2, convert them to decimal values d1 and d2, then combine them into a uint64 value that has enough precision to hold the result.
bin2uint64 = #(b) uint64(bin2dec(b(:,1:32)))*(2^32) + uint64(bin2dec(b(:,33:64)));
(This assumes that you have your data in the same format required by bin2dec, i.e. a vector of char. If you have a vector of numeric values, just add in a b = char(b+'0');)
Given an initial value
>> b = 1100110010111100101101111010100010101010010011010010000110011010
>> d = bin2uint64(b)
d = 14752868414398472602
>> r = dec2bin(d, 64)
r = 1100110010111100101101111010100010101010010011010010000110011010
>> any(b-r)
ans = 0
Since b-r gives all zeros, the values are identical. You can pass the entire nx64 matrix as b and it will convert all of the values at once.
>> bin2uint64(char(randi([0 1], 20, 64) + '0'))
ans =
4169100589409210726
8883634060077187622
15399652840620725530
12845470998093501747
14561257795005665153
1133198980289431407
13360302497937328511
563773644115232568
8825360015701340662
2543400693478304607
11786523850513558107
8569436845019332309
2720129551425231323
5937260866696745014
4974981393428261150
16646060326132661642
5943867124784820058
2385960312431811974
13146819635569970159
6273342847731389380
You'll notice that I manually converted my random array to char. Assuming your input is numeric, you'll have to convert it first:
Achar = char(A + '0');
Yes, this is a pain, MATLAB should have included a destination type parameter in bin2dec, but they didn't. Now you can use your linked solution to find the matchings.
Converting your values:
Assuming your matrices A and B contain the numeric values 0 and 1, you can easily convert the rows to uint64 data types without precision loss using the bitset and sum functions (and bsxfun for a small efficiency boost):
result = sum(bsxfun(#(bit, V) bitset(uint64(0), bit, V), 64:-1:1, A), 2, 'native');
Compared to the solution from beaker, this one is over 4 times faster for a 10,000 row matrix:
% Sample data:
A = randi([0 1], 10000, 64);
% Test functions:
bin2uint64 = #(b) uint64(bin2dec(b(:,1:32)))*(2^32) + uint64(bin2dec(b(:,33:64)));
beaker_fcn = #(A) bin2uint64(char(A+'0'));
gnovice_fcn = #(A) sum(bsxfun(#(b, V) bitset(uint64(0), b, V), 64:-1:1, A), 2, 'native');
% Accuracy test:
isMatch = isequal(beaker_fcn(A), gnovice_fcn(A)); % Return "true"
% Timing:
timeit(#() beaker_fcn(A))
ans =
0.022865378234183
timeit(#() gnovice_fcn(A))
ans =
0.005434031911843
Computing nearest matches:
You provide a link to some solutions for finding the nearest matches for A in B. However, the fact that you are using unsigned integer types requires some modification. Specifically, order matters when subtracting values due to integer overflow. For example uint64(8) - uint64(1) gives you 7, but uint64(1) - uint64(8) gives you 0.
Here's the modified solution for unsigned integers, applied to the sample data you provide:
A = uint64([1 5 7 3 2 8]);
B = uint64([4 12 11 10 9 23 1 15]);
delta = bsxfun(#(a, b) max(a-b, b-a), A(:), reshape(B, 1, []));
[~, index] = min(delta, [], 2);
result = B(index)
result =
1×6 uint64 row vector
1 4 9 4 1 9 % As expected!

Matlab: mean and stddev in a cell

In a single array it's pretty simple to get the mean or standard deviation (std) of its numbers, however in a cell, whose data doesn't have the same size in each of its positions I couldn't do mean2 or std2.
I know it's possible to do something if I copy all of the data in a single row or single column but I just wanted to ask if someone knows if there is a single formula to do it?
Thanks
You can use cellfun to compute per-cell mean and std:
cell_mean = cellfun(#mean, my_cell);
cell_std = cellfun(#std, my_cell);
For example:
>> my_cell = {[1,2,3,6,8], [2,4,20]}
>> cellfun(#mean, my_cell)
ans =
4.0000 8.6667
>> cellfun(#std, my_cell)
ans =
2.9155 9.8658
If you want the mean and/or std of all the elements in all the cells, you can:
>> mean([my_cell{:}])
ans =
5.7500
>> std([my_cell{:}])
ans =
6.2048
And, if your cell elements are all of different sizes, you can use cell2mat to assist you:
>> mean(cell2mat(cellfun(#(x) x(:)', my_cell, 'uni', 0)))
ans =
5.7500
>> std(cell2mat(cellfun(#(x) x(:)', my_cell, 'uni', 0)))
ans =
6.2048

How to apply a probability to a cell in MATLAB?

Just a simple question today. If I have an m*n matrix and I want to cycle through every value in it and apply a probability based function.
Basically, if the probability is p, then each value in the matrix has p chance of having the function applied to it.
I have the loop and the function itself all worked out, but I haven't found how to actually apply the probability itself.
Any advice would be greatly appreciated! Thanks in advance.
Here's your data matrix:
>> X = reshape(1:9, 3, 3);
and you want to (possibly) apply the following function to every element (note how I've vectorized it, so that it can take a matrix as an argument)
>> f = #(x) x.^2;
You want to apply the function with probability p
>> p = 0.25;
So generate some random numbers between 0 and 1, and see which ones are less than p
>> idx = rand(3,3) < p;
And now apply the function to the relevant indexes
>> X(idx) = f(X(idx));
Here's your result:
>> X
X =
1 16 7
2 5 64
3 6 81
The trick is that you can generate the random numbers first, and then apply the other formulas.
For example:
R = rand(m,n) < p
Now each value of R(row,col) corresponds to the outcome that you need to process your original matrix(row,col).
So I suggest applying your function to every cell and then setting the values to a default value based on some probability. So lets assume M is the result of applying to function to everycell:
default = NaN % Or 0 or whatever
p = 0.8;
M(rand(size(M)) > p) = default;
I think you might have to reshape m after this... not sure
M = reshape(M, m, n);

how to eliminate complex number in a vector in Matlab

In Matlab, suppose there is a vector whose elements can be complex or real. I was wondering how to remove the nonreal elements, and consequently reduce the size of the vector? Thanks and regards!
Use the REAL and IMAG functions:
>> x = [1+i; 4+3i; 5+6i]
x =
1 + 1i
4 + 3i
5 + 6i
>> real(x)
ans =
1
4
5
>> imag(x)
ans =
1
3
6
EDIT
The above doesn't answer the poster's question. This does.
Use the FIND and REAL functions:
>> v = [1+i; 2; 3]
v =
1 + 1i
2
3
>> v(v == real(v))
ans =
2
3
You can also avoid testing in a loop using Matlab's vector syntax:
x = [1, 2, 3+1i, 4+2i, 5+3i, 6, 7, 8+4i, 9+0.000001i]
y = x(imag(x) == 0);
z = real(x(abs(imag(x)) < 0.00001));
y should be [1,2,6,7] and z should be [1,2,6,7,9]
imag(x) == 0 yields a logical vector with true values whenever the equality condition holds. x(<logical vector>) yields a new vector with only the elements of x where <logical vector> was true.
That's a very unusual thing to ask. Since the imaginary part is a floating point number, you can't really tell which number is a real number and which number is very close to a real number. Such function doesn't exist in Matlab since it's not very clear how it would be useful for anything (it doesn't make much sense to remove those numbers). Specifying your actual purpose here might help you get better answers.
If you want to ensure that only real numbers are left in the vector, you can use the following (it doesn't work with matrices and vertical rows, but you've got the idea):
x = [1, 2, 3+1i, 4+2i, 5+3i, 6, 7, 8+4i, 9+0i]
z = []
for k = [1:length(x)]
if imag(x(k)) == 0
z = [z, real(x(k))]
endif
endfor
If you want to keep all numbers that are close to a real number, but could have some small non-zero imaginary part, you can use the following:
x = [1, 2, 3+1i, 4+2i, 5+3i, 6, 7, 8+4i, 9+0.000001i]
z = []
for k = [1:length(x)]
if abs(imag(x(k))) < 0.00001
z = [z, real(x(k))]
endif
endfor
Of course, if you tell us what your actual criterion is, it would be much easier to give you a better idea. Are you looking for the real solutions to some sort of equation or system of equations, real roots of a polynomial? In this case, the first one might miss a real solution because of the approximation error, and the second one can give you things that aren't solutions.