MATLAB compute length of an integer - matlab

I'm trying to compute the length of an integer.
For example:
a = 1.1234; b = 33; c = 100; d = -222;
e = lengthint([a,b,c,d])
Expected output:
e = 1 2 3 3
I tried using this:
e = max(ceil(log10(abs([a,b,c,d]))),1)
but this is the output:
e = 1 2 2 3
So there is a problem with numbers that are multiples of 10.

You can do something like this -
A = [a,b,c,d]
lens = floor(log10(abs(A)))+1
lens(lens<0) = 0 %// Assuming that 0.xx numbers to have zero lengths
Sample runs:
Case #1:
>> A = [0.00001234, 1.1234, 33, 10, -222];
>> lens = floor(log10(abs(A)))+1;
>> lens(lens<0) = 0
lens =
0 1 2 2 3
Case #2:
>> A = [-0.00001234, 1.1234 33, 10, -222, 0];
>> lens = floor(log10(abs(A)))+1;
>> lens(lens<0) = 0
lens =
0 1 2 2 3 0

Another option would be to convert them to strings and check the length:
cellfun(#(x)length(num2str(abs(fix(x)))),{a,b,c,d});
the only complication is that you need cells to keep your strings separate.
Output from #Divakar's example input:
>> a1 = 0.00001234; a2 = 1.1234; b = 33; c = 100; d = -222;
>> cellfun(#(x)length(num2str(abs(fix(x)))),{a1,a2,b,c,d})
ans =
1 1 2 3 3
so it will obviously not give 0 for the 1e-5 case.

Related

Find the missing combinations

I am using this block of code to get all the possible combinations of the rows of the matrix having thee rows. The code is as follows:
sample = [1 1 ; 2 2; 3 3];
v = [];
for i = 1:size(sample,1)-1
v = [v;(sample(i,:))];
for j = 1:size(sample,1)
if isequal(ismember(sample(j,:),v,'rows'),0)
display([v;sample(j,:)]);
else
j = j+1;
end
end
end
This code gives me the following output:
ans =
1 1
2 2
ans =
1 1
3 3
ans =
1 1
2 2
3 3
But I need output like this:
ans =
1 1
ans =
2 2
ans =
3 3
ans =
1 1
2 2
ans =
1 1
3 3
ans =
2 2
3 3
ans =
1 1
2 2
3 3
Only a small change would be enough to get the desired result.
What about this:
% getting the number of rows
n_row = size(sample,1);
% calculating all possible permutations of the rows
v = perms([1:n_row]);
disp('---')
% now we iterate over the permutations, as you want to have matrixes of 1,
% 2 and 3 rows
for i = 1: size(v,2)
idx1 = v(:,1:i);
% remove repeated answers
idx1 = unique(idx1,'rows');
% now we iterate over the answers and display
for j = 1:size(idx1,1)
idx2 = idx1(j,:);
answer = sample(idx2,:);
disp(answer)
disp('---')
end
end

Using 'find' on rows of a matrix without looping

If A is a nx by ny matrix of zeros and ones and I want to find the index of the the first and last zeros in each row. Currently I'm doing the following:
for ix = 1:nx
lhs_i = find(A(ix,:) < 1,1,'first');
rhs_i = find(A(ix,:) < 1,1,'last');
if ~isempty(lhs_i)
lhs(ix,k) = lhs_i;
rhs(ix,k) = rhs_i;
else
lhs(ix,k) = NaN;
rhs(ix,k) = NaN;
end
end
I'm sure there is a better way that doesn't involve a loop. Any suggestions?
You can use accumarray -
[R,C] = find(A==0);
out = zeros(size(A,1),2)
out(1:max(R),:) = [accumarray(R,C,[],#min) accumarray(R,C,[],#max)]
Finally, if need be, replace the zeros with NaNs, but zeros themselves look like good specifiers of invalid rows (rows without zeros).
Sample run -
>> A
A =
3 1 3 3 4
0 3 0 2 0
0 0 4 4 0
1 4 1 4 2
>> [R,C] = find(A==0);
>> out = zeros(size(A,1),2);
>> out(1:max(R),:) = [accumarray(R,C,[],#min) accumarray(R,C,[],#max)]
out =
0 0
1 5
1 5
0 0
Here's another using bsxfun and minmax -
P = bsxfun(#times,A==0,1:size(A,2));
P(P==0) = nan;
out = minmax(P)
With this solution, Inf/-Inf would act as the invalid specifier.
Sample run -
>> A
A =
0 4 0 2 2
3 4 3 1 1
0 4 3 1 2
1 0 3 4 0
>> P = bsxfun(#times,A==0,1:size(A,2));
>> P(P==0) = nan;
>> minmax(P)
ans =
1 3
-Inf Inf
1 1
2 5

Replace rows having at least one duplicate number or one zero by a user defined row

I have a matrix having rows with repeated numbers.
A= [ 2 3 6;
4 7 4;
8 7 2;
1 3 1;
7 8 2 ]
The codes below find those rows and replace them with a Dummy_row [1 2 3]
new_A=[ 2 3 6;
1 2 3;
8 7 2;
1 2 3;
7 8 2 ]
This are the codes:
CODE NUMBER 1 (#Bruno)
Dummy_row = [1 2 3];
b = any(~diff(sort(A,2),1,2),2);
A(b,:) = repmat(Dummy_row,sum(b),1)
CODE NUMBER 2 (#Kamtal)
Dummy_row = [1 2 3];
b = diff(sort(A,2),1,2);
b = sum(b == 0,2);
b = b > 0;
c = repmat(Dummy_row,sum(b),1);
b = b' .* (1:length(b));
b = b(b > 0);
newA = A;
newA(b,:) = c
Note: both codes Number 1 and 2 perform the task efficiently.
Question
How can this code(either code num 1 or num 2) be modified such that it also replaces any rows having at least one zero with the Dummy_row?
Code 1
b = any(~diff(sort(A,2),1,2),2) | any(A==0,2); % <-- Only change
A(b,:) = repmat(Dummy_row,sum(b),1);
Code 2
b = diff(sort(A,2),1,2);
b = sum(b == 0,2);
b = (b > 0) | any(A==0,2); % <-- Only change
c = repmat(Dummy_row,sum(b),1);
b = b' .* (1:length(b));
b = b(b > 0);
newA = A;
newA(b,:) = c;
By the way: Code1 basically does the same thing that Code2 does, just that it uses logical-indexing instead of doing the unnecessary conversion from logical indexes to index positions.

Assigning indexes in MatLab using sub2ind

I have 3 data sets, two with coordinates and one with data with the length of n with a loop I would assign the data in this way
MAT = zeros(m, n);
for i = 1:n
MAT(Z(i), X(i)) = MAT(Z(i), X(i)) + DATA(i);
end
I want to do it without a loop since what I am trying to do is something like:
MAT = zeros(m, n);
mn = size(MAT);
MAT(sub2ind(mn, Z, X)) = MAT(sub2ind(mn, Z, X)) + DATA;
Anyone has an idea how to make it properly and efficiently?
Cheers.
You should use the function accumarray, for example:
Let:
>> Z = [ 1 2 4 3 1];
>> X = [3 2 1 4 3];
>> D = [5 6 7 8 -10];
>> m = 4;n = 4;
Then we have:
>> MAT = accumarray([Z(:),X(:)],D(:),[m,n])
MAT =
0 0 -5 0
0 6 0 0
0 0 0 8
7 0 0 0

How to initialize a vector in MATLAB as per a pattern?

I am completely new to MATLAB.This may be a rather basic question.
Given numerical values for size, extras and max, I need to initialize a 1 X N vector such that the first size elements are 1, the next size are 2, the next size are 3 and so on till the last size elements are set to max. So I need to initialize size number of elements successively to x such that x increments from 1 to max. The extras are the number of leftover cells which are initialized to 0. To illustrate:
size = 3; %# (is same as the quotient of N/max)
extras = 1; %# (is same as remainder of N/max)
max = 3;
N = 10;
original_vector = [0 0 0 0 0 0 0 0 0 0];
The desired output is
Required_vector = [1 1 1 2 2 2 3 3 3 0]
Maybe something using the Kronecker product:
N = 10;
max = 3;
extras = rem(N, max);
size = floor(N/max);
v = [kron([1 : max], ones(1,size)) zeros(1, extras)];
I took a guess about how extras and size are calculated. You said size is N % max and extras is N rem max, but those are the same thing(?).
Some reshaping acrobatics should do it:
>> size = 3;
>> max = 3;
>> N = 10;
>> v = zeros(1, N);
>> v(1:size*max) = reshape(cumsum(ones(max, size))', size*max, 1)
v =
1 1 1 2 2 2 3 3 3 0
Another example:
>> size = 4;
>> max = 5;
>> N = 23;
>> v(1:size*max) = reshape(cumsum(ones(max, size))', size*max, 1)
v =
Columns 1 through 18
1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5
Columns 19 through 23
5 5 0 0 0
This is a quite dirty implementation, but as you say you are very new to MATLAB, it might be better for you to see how you can more or less brute force a solution out. The trick here is the index reference done on Vec to place the numbers in. I have ignored the parameter extras and instead fill the vector up as best can be with the elements
N = 23;
max = 3;
size = 4;
Vec = zeros(N,1);
for i=1:max
for j=1:size
Vec((i-1)*size +1 + (j-1)) = i;
end
end
Vec'
extra = sum(Vec==0)
Output:
ans =
1 1 1 1 2 2 2 2 3 3 3 3 0 0 0 0 0 0 0 0 0 0 0
extra =
11
A slight modification of #b3's solution:
N = 10;
mx = 3;
sz = floor(N/mx);
v = zeros(1,N);
v(1:mx*sz) = repmat(1:mx,sz,1)