How to access to numbers from *.txt file in matlab? - matlab

I have a data.txt file like:
123 124 125 126
I want to compare these number against num
My code is like this
data= textread('data.txt','%d');
num = 125;
if num == data
b = 1;
else
b = 0;
end
but answer shows 0 ( b = 0 )
how to scan these numbers?

Here is a quote from the doc page of eq function (the functional form of == operator):
A == B
If one input is scalar and the other a nonscalar array, then the
scalar input is treated as if it were an array having the same
dimensions as the nonscalar input array. In other words, if input A is
the number 100, and B is a 3-by-5 matrix, then A is treated as if it
were a 3-by-5 matrix of elements, each set to 100. MATLAB returns an
array of the same dimensions as the nonscalar input array.
And here is the relevant section from the docs of if statement:
if expression
statements
end
An evaluated expression is true when the result is nonempty and
contains all nonzero elements (logical or real numeric). Otherwise,
the expression is false.
So perhaps you meant to use:
if any(data == num)
disp('number found')
end

Related

How to find an matching element (either number or string) in a multi level cell?

I am trying to search a cell of cell arrays for a matching number (for example, 2) or string ('text'). Example for a cell:
A = {1 {2; 3};4 {5 'text' 7;8 9 10}};
There is similar question. However, this solution works only, if you want to find a number value in cell. I would need a solution as well for numbers as for strings.
The needed output should be 1 or 0 (the value is or is not in the cell A) and the cell level/deepness where the matched element was found.
For your example input, you can match character vectors as well as numbers by replacing ismember in the linked solution with isequal. You can get the depth at which the search value was found by tracking how many times the function has to go round the while loop.
function [isPresent, depth] = is_in_cell(cellArray, value)
depth = 1;
f = #(c) isequal(value, c);
cellIndex = cellfun(#iscell, cellArray);
isPresent = any(cellfun(f, cellArray(~cellIndex)));
while ~isPresent
depth = depth + 1;
cellArray = [cellArray{cellIndex}];
cellIndex = cellfun(#iscell, cellArray);
isPresent = any(cellfun(f, cellArray(~cellIndex)));
if ~any(cellIndex)
break
end
end
end
Using isequal works because f is only called for elements of cellArray that are not themselves cell arrays. Use isequaln if you want to be able to search for NaN values.
Note this now won't search inside numeric, logical or string arrays:
>> A = {1 {2; 3};4 {5 'text' 7;8 9 [10 11 12]}};
>> is_in_cell(A, 10)
ans =
logical
0
If you want that, you can define f as
f = #(c) isequal(value, c) || isequal(class(value), class(c)) && ismember(value, c);
which avoids calling ismember with incompatible data types, because of the 'short-circuiting' behaviour of || and &&. This last solution is still a bit inconsistent in how it matches strings with character vectors, just in case that's important to you - see if you can figure out how to fix that.

MATLAB - Check matrix to see if two consecutive numbers = 0

I have a matrix being created in MATLAB but need to check if any two consecutive numbers (by row) = 0 and if it does output with a yes or no without showing the answers. Ive put my code below my final loop is returning errors and im not too sure how to go about this.
%%Input positive integer
n=input('Give a positive integer greater than 1: ');
%%Error for below 1
if n<=1
error('The value given is less than or equal to 1')
end
%%loop for vector v
for i=1:n
v(i)=2^i*3;
end
%display vector
v
A=randi([-5,5],n,n);
A
x = 1;
consecutive = false;
for i = 1:25
if (A(x) + A(x+1) = 0);
consecutive = true;
end
end
There's a lot wrong with the code of your final loop:
You set x to 1 and use it as an index into A, but never change it from 1.
As Amit points out, you are using = (used for assignment) when you should be using == (the equality operator).
As Gondrian points out, you are testing if a sum is equal to zero, but from your description it sounds like you should be testing if each value is zero.
Your loop iterates 25 times (i = 1:25), but it's not clear why, since your matrix A is of size n-by-n.
Instead of using a for loop, it's possible to do this with indexing instead. Since you are checking for consecutive zeroes by row, this is what it would look like:
zeroPairs = (A(:, 1:(n-1)) == 0) & (A(:, 2:n) == 0);
consecutive = any(zeroPairs(:));
The term A(:, 1:(n-1)) gets all of the "left" values in each pairwise comparison and the term A(:, 2:n) gets all of the "right" value. These are compared to 0, then combined. This creates an n-by-(n-1) matrix zeroPairs where a value of true indicates where a pair of consecutive zeroes occurs. This matrix is reshaped into a column vector and any is used to check if a value of true is present anywhere.
You will need to change your if block as follows.
if (A(x) + A(x+1) == 0);
consecutive = true;
end
Notice the == instead of just =. The first one is for comparison and the second one is for assignment. This will get rid of the error that you are currently getting. There may be other issues in the algorithm of your code but I did not examine or try to fix that.
btw:
'if any two consecutive numbers (by row) = 0'
If I understand you right, you should try 'if A(x) == 0 && A(x+1) == 0';
because '(A(x) + A(x+1) == 0)' would be true for -5 and 5, as it equals to 0. But -5 and 5 are not two consecutive zeros.
(or even look at the 'diff' function. It will return a 0 if two following numbers are the same)
To show a vectorized, more Matlab-like approach:
v = 0; % sought value
C = 2; % desired number of consecutive values in a row
consecutive = nnz(conv2(double(A==v), ones(1,C))==C)>0;
This compares each entry of A with the value v, and then applies 2D convolution with a row vector of C ones. Any C horizontally-consecutive entries of A with value v will produce an entry equal to C in the convolution result. So we check if the number of such entries is positive.

if statement with for loop

I am writing a function to calculate a value of p.
The formula is p=r*q + pa. The pa value is column vector which i have got from the ode45 function. I have to change the value of q w.r.t time i.e from 0 to 1 sec q=500, from 1 to 2 sec q=0.
I have written this program:
function [p] = fom(t,pa)
r=0.007;
tin=1;
t=0:0.01:2;
if t <=tin
q = 600;
else t <= 2
q = 0;
end
[t,pa]=ode45('FOM1',[t],[0])
for i=[palv]
p=(r*q)+(i);
end
end
The problem is I am getting correct values after 1 sec in my output but before 1 sec where q is 0 values are not changing.
Is this if statement correct?
The problem is the following code snippet:
if t <=tin
q = 600;
else t <= 2
q = 0;
end
With t <= tin, you compare each element of vector t with tin. The result is again a vector, which contains 1 for all elements in t, which are smaller than tin, and 0 for all elements which are larger than tin, i.e.
[ 1 1 ... 1 1 0 0 ... 0 ]
According to the documentation, if evaluates the following:
An expression is true when its result is nonempty and contains only nonzero elements (logical or real numeric). Otherwise, the expression is false.
As the vector contains ones and zeros, i.e. not only nonzero elements, the this always evaluates to false and the else clause will be executed. q will therefore be a scalar, not a vector, which is always 0. To get a vector q, which is 600 for all t <= tin and zero otherwise, you can use
q = 600*(t <= tin);
which creates such a vector as printed above, and multiplies it by 600.
Now, a number of comments on your code:
Regarding the else: in the else, you can't have any other conditions, so t <= 2 will just be executed and printed to the console, but this does nothing, so you can leave that away.
You have t and pa as inputs to the function, but never use them. t is simply overwritten. So either leave t an input and don't overwrite it, or leave it away as input. Further, you can remove pa as input, as you calculate it using ode45.
I assume for i = palv is a typo and should be for i = pa.
In this for loop, by calling p=(r*q)+(i);, p gets overwritten in every iteration, i.e. the resulting p will be r*q plus the last element of pa.
You can create a vector p without a for loop using
p = r*q + pa
Everything together, the function becomes
function p = fom(t)
r=0.007;
tin=1;
q = 600 * (t <= tin);
[t,pa]=ode45('FOM1',[t],[0])
p = r*q + pa
end
and can be called e.g. by
t = 0:0.01:2
p = fom(t);

How to perform XOR in a recursive scenario

I have a 1x5 char matrix. I need to perform a bitwise XOR operation on all the elements in the matrix.If T is the char matrix , I need a matrix T' such that
T'= T XOR (T-1)' for all T
T for T=1
Let the char matrix be T
T=['0000000000110111' '0000000001000001' '0000000001001010' '0000000010111000' '0000000000101111']
T'=['0000000000110111' '0000000001110110' '0000000000111100' '0000000010000100' '0000000010101011']
ie; Leaving the first element as such , I need to XOR all the other elements with the newly formed matrix. I tried the following code but I'm unable to get the correct result.
Yxor1d = [T(1) cellfun(#(a,b) char((a ~= b) + '0'), T(2:end), T'(1:end-1), 'UniformOutput', false)]
I need to perform the XOR operation such that , for obtaining the elements of T'
T' (2)= T(2) XOR T' (1)
T' (3)= T(3) XOR T' (2)
It'll be really helpful to know where I went wrong.Thanks.
You are using cellfun when a cell array is expected as the input. You are using a character array, and what you're actually doing is taking each of those 5 strings and creating a single character array out of them. Chaining those strings together is actually performing a character concatenation.
You probably don't want that. To fix this, all you have to do is make T a cell array by placing {} characters instead of array ([]) characters to declare your characters:
T={'0000000000110111' '0000000001000001' '0000000001001010' '0000000010111000' '0000000000101111'};
Because you have edited your post after I provided my answer, my previous answer using cellfun is now incorrect. Because you are using a recurrence relation where you are referring to the previous output rather than input, you can no longer use cellfun. You'll need to use a for loop. There are probably more elegant ways to do it, but this is the easiest if you want to get something working.
As such, initialize an output cell array that is the same size as the input cell array like above, then you'll need to initialize the first cell to be the first cell of the input, then iterate through each pair of input and output elements yourself.
So do something like this:
Yxor1d = cell(1,numel(T));
Yxor1d{1} = T{1};
for idx = 2 : numel(T)
Yxor1d{idx} = char(double(T{idx} ~= Yxor1d{idx-1}) + '0');
end
For each value i of T', we XOR with the current input at T{i} with the previous output of T'{i-1}.
Use the above and your input cell array T, we get:
Yxor1d =
Columns 1 through 3
'0000000000110111' '0000000001110110' '0000000000111100'
Columns 4 through 5
'0000000010000100' '0000000010101011'
This matches with your specifications in your modified post.
Edit: There is a solution without a loop:
T=['0000000000110111';'0000000001000001';'0000000001001010';'0000000010111000' ;'0000000000101111'];
Yxor = dec2bin(bi2de(mod(cumsum(de2bi(bin2dec(T))),2)),16)
Yxor =
0000000000110111
0000000001110110
0000000000111100
0000000010000100
0000000010101011
This uses the fact that you effectively want a cumulative xor operation on the elements of your array.
For N booleans it should be either any one of them or else all of them. So if you do a cumulative sum of each of your bits, the sum should be an odd number for a true answer to 'xor'.
The one liner above can be decomposed like that:
Y = bin2dec(T) ; %// convert char array T into decimal numbers
Y = de2bi( Y ) ; %// convert decimal array Tbin into array of "bit"
Y = cumsum(Y) ; %// do the cumulative sum on each bit column
Y = mod(Y,2) ; %// convert all "even" numbers to '0', and 'odd' numbers to '1'
Y = bi2de(Y) ; %// re-assemble the bits into decimal numbers
Yxor = dec2bin(Y,16) ; %// get their string representation
Note that if you are happy to handle arrays of bits (boolean) instead of character arrays, you can shave off a few lines from above ;-)
Initial answer (simpler to grasp, but with a loop):
You can use the bitxor function, but you have to convert your char array in numeric value first:
T=['0000000000110111';'0000000001000001';'0000000001001010' ;'0000000010111000' ;'0000000000101111'];
Tbin = bin2dec(T) ; %// convert to numeric values
Ybin = Tbin ; %// pre-assign result, then loop ...
for idx = 2 : numel(Tbin)
Ybin(idx) = bitxor( Ybin(idx) , Ybin(idx-1) ) ;
end
Ychar = dec2bin(Ybin,16) %// convert back to 16bit char array representation if necessary
Ychar =
0000000000110111
0000000001110110
0000000000111100
0000000010000100
0000000010101011
edited answer after you redefined your problem

|| usage in Matlab

I am writing an easy IF condition. The function is to judge each row of the matrix to be certain vectors. The code is as follows:
if (compareM(i,:)==[1, 0])||(compareM(i,:) ==[2, 1])
match_1 = match_1 +1;
else
mismatch_1 = mismatch_1 +1;
end
The error said ''Operands to the || and && operators must be convertible to logical scalar values''.
compareM is a n by 2 matrix and I wonder if the error is made by || operation. Thanks in advance!
If you are comparing vectors, not scalar values, you have to use | operator. As a result you get logical vector of element-by-element pairwise comparison. To use it in IF statement you have to convert either each logical statement (then use ||) or the result of | the to scalar with ALL, ANY or other function.
If you want to compare to vectors for equality use ISEQUAL function as
if isequal(compareM(i,:)==[1, 0]) || isequal(compareM(i,:)==[2, 1])
compareM(i, :) evaluates to a 1x2 numeric array, so compareM(i,:)==[1, 0] evaluates to a 1x2 logical array. The same for the expression to the right of the || sign. But you need a single logical value on each side of ||, not a 1x2 array of logical values.
If you want this expression to evaluate to true if both values on the lhs of == are the same as the corresponding elements on the rhs, wrap all() around each side:
all(compareM(i,:)==[1, 0]) || all(compareM(i,:) ==[2, 1])
if ((compareM(i,:)==[1, 0])||(compareM(i,:) ==[2, 1]))
match_1 = match_1 +1;
else
mismatch_1 = mismatch_1 +1;
end
Note the outer enclosing parentheses.