I have an array in MATLAB, and I wanted to display the positive symbol, "+" in front of positive elements, and keep the negative symbol, "-" in already existing negative values. I thought I could do the following:
I was thinking of constructing a sort of cell string or string array, and having an if, else system where if the numbers magnitude was >0, then I should store the value as '+' concatenated with the conversion of the element. If it was 0, just do a straight up char conversion since 0 has no sign, and if it was negative, just convert it. I know what to do, however, logistically, I think my order of commands is whacky.
How can I implement this?
I have the following script for an array x, but it just spews out values, I want an orderly string array I can copy and paste for use outside of MATLAB.
x;
pos = '+';
bound = length(x);
for i=1:bound
if(x(i)==0)
num2str(x(i))
end
if(x(i)>0)
num2str(x(i))
strcat(pos,num2str(x(i)))
end
if(x(i)<0)
num2str(x(i))
strcat(pos,num2str(x(i)))
end
end
I think you are searching for this.
Let's make an example.
First type in your command window :
test = 5;
Then:
sprintf('%+d',test)
You should have in this way what you want.
Of course you need to adapt it to your case. I suggest you to read this.
I hope it helps.
Related
I had a strange error in a VB6 app this morning and it all stems from the fact that IsNumeric is not working as I expected. Can someone shed some light on why? To me this seems like a bug.
This code displays 4.15877E+62 in a message box:
Dim strMessage As String
strMessage = "0415877D57"
If IsNumeric(strMessage) Then
MsgBox CDbl(strMessage)
Else
MsgBox "not numeric"
End If
I am guessing that the runtime engine is incorrectly thinking that the D is in fact an E?
I think this is a bug though as the exact same code in VB.NET outputs not numeric
Is this a known issue with IsNumeric?
If you check the VB6 docs:
Note Floating-point values can be expressed as mmmEeee or mmmDeee, in which mmm is the mantissa and eee is the exponent (a power of 10). The highest positive value of a Single data type is 3.402823E+38, or 3.4 times 10 to the 38th power; the highest positive value of a Double data type is 1.79769313486232D+308, or about 1.8 times 10 to the 308th power. Using D to separate the mantissa and exponent in a numeric literal causes the value to be treated as a Double data type. Likewise, using E in the same fashion treats the value as a Single data type.
I've been using my own IsNumber function for a long time exactly because of this situation. IsNumeric can also return true for certain money symbols, like this: IsNumeric("$34.20").
My IsNumber function looks like this:
Public Function IsNumber(ByVal Data As String) As Boolean
If Data = "" Then
IsNumber = False
Exit Function
End If
IsNumber = IsNumeric(Data & "e0")
End Function
The idea here is... if there is already an e or d in the data, adding another will cause the data to NOT be numeric using the IsNumeric check. You can easily change this function to only allow for integers by replacing "e0" with ".0e0". Want just positive integers? then use this: IsNumeric("-" & Data & ".0e0")
The only downside of this method is that an empty string normally is not numeric, but when you append "e0" to it, it becomes numeric so you need to add a check for that, like I did in my code.
I suggest making a custom validator. Do you want to allow 0-9 only? What about negatives? Commas? I never cared for Microsoft's implementation, but I understand it.
I am trying to read an excel sheet and then and find cells that are not empty and have date information in them by finding two '/' in a string
but matlab keeps to erroring on handling cell type
"Undefined operator '~=' for input arguments of type 'cell'."
"Undefined function 'string' for input arguments of type 'cell'."
"Undefined function 'char' for input arguments of type 'cell'."
MyFolderInfo = dir('C:\');
filename = 'Export.xls';
[num,txt,raw] = xlsread(filename,'A1:G200');
for i = 1:length(txt)
if ~isnan(raw(i,1))
if sum(ismember(char(raw(i,1)),'/')) == 2
A(i,1) = raw(i,1);
end
end
end
please help fixing it
There are multiple issues with your code. Since raw is a cell array, you can't run isnan on it, isnan is for numerical arrays. Since all you're interested in is cells with text in them, you don't need to use raw at all, any blank cells will not be present in txt.
My approach is to create a logical array, has_2_slashes, and then use it to extract the elements from raw that have two slashes in them.
Here is my code. I generalized it to read multiple columns since your original code only seemed to be written to handle one column.
filename = 'Export.xls';
[~, ~, raw] = xlsread(filename, 'A1:G200');
[num_rows, num_cols] = size(raw);
has_2_slashes = false(num_rows, num_cols);
for row = 1:num_rows
for col = 1:num_cols
has_2_slashes(row, col) = sum(ismember(raw{row, col}, '/')) == 2;
end
end
A = raw(has_2_slashes);
cellfun(#numel,strfind(txt,'/'))
should give you a numerical array where the (i,j)th element contains the number of slashes. For example,
>> cellfun(#numel,strfind({'a','b';'/','/abc/'},'/'))
ans =
0 0
1 2
The key here is to use strfind.
Now you may want to expand a bit in your question on what you intend to do next with txt -- in other words, specify desired output more, which is always a good thing to do. If you intend to read the dates, it may be better to just read it upfront, for example by using regexp or datetime as opposed to getting an array which can then map to where the dates are. As is, using ans>=2 next gives you the logical array that can let you extract the matched entries.
In my program I need to ask the user a string (ex: 'C4') and then obtain the corresponding index to that string on the following vector:
labels=['C2';'C#2';'D2';'D#2';'E2';'F2';'F#2';'G2';'G#2';'A2';'A#2';'B2';'C3';'C#3';'D3';'D#3';'E3';'F3';'F#3';'G3';'G#3';'A3';'A#3';'B3';'C4';'C#4';'D4';'D#4';'E4';'F4';'F#4';'G4';'G#4';'A4';'A#4';'B4';'C5';'C#5';'D5';'D#5';'E5';'F5';'F#5';'G5';'G#5';'A5';'A#5';'B5'];
To ask the string is simple, used input and it worked on octave, but to find the index I couldn't make it work. I tried using find, find(ismember( and also with a for cycle but nothing seems to work.
Appreciate the help
Thanks.
Use strcmp (and note labels should be a cell array, as the strings have different lengths):
labels = {'C2';'C#2';'D2';'D#2';'E2';'F2';'F#2';'G2';'G#2';'A2';'A#2';'B2';'C3';'C#3';'D3';'D#3';'E3';'F3';'F#3';'G3';'G#3';'A3';'A#3';'B3';'C4';'C#4';'D4';'D#4';'E4';'F4';'F#4';'G4';'G#4';'A4';'A#4';'B4';'C5';'C#5';'D5';'D#5';'E5';'F5';'F#5';'G5';'G#5';'A5';'A#5';'B5'};
str = 'C4';
index = find(strcmp(str,labels));
You can use strcmpi instead of strcmp if case is not important.
I have one array of strings that I want to use to pull out samples from a larger matrix of data that I have. Right now I have the one array of strings, 1200x1. And my actual data 'names' (string array that denotes what the values correspond to 6855x1, and 'data' is 6855x2.
This is what I came up with:
C = intersect(names,sites) %To find common strings
%To find where these strings are in my original dataset:
Q=zeros(length(C),1)
for i=1:length(C)
for j=1
while strcmp(C(i),names(j))==0
j=j+1
Q(i)=j
end
end
end
%To then use the above values to compile a new vector with the actual data values from 'data':
A=zeros(length(Q),1)
for i=1:length(Q)
A(i) = mock(Q(i),1)
The only problem is I am running the second set of loops I listed right now, and it is obvious that it will take several hours. I think there must be a quicker way without setting up three loops. Does anyone know a better method?
The first thing to note is that your loop over Q can be trivially accelerated, as:
A = mock(Q,1);
although I suspect that you meant data(Q,2).
If you store your name list in a cell array rather than a regular array, you should be able to accelerate things further. Assume that data is a cell array, names{1:6855} and value list numbers(1:6855).
A = zeros(length(C),1);
for i1=1:length(C)
A(i1)=numbers(strcmp(C(i1),names));
end
I am trying to produce the following:The new values of x and y are -4 and 7, respectively, using the disp and num2str commands. I tried to do this disp('The new values of x and y are num2str(x) and num2str(y) respectively'), but it gave num2str instead of the appropriate values. What should I do?
Like Colin mentioned, one option would be converting the numbers to strings using num2str, concatenating all strings manually and feeding the final result into disp. Unfortunately, it can get very awkward and tedious, especially when you have a lot of numbers to print.
Instead, you can harness the power of sprintf, which is very similar in MATLAB to its C programming language counterpart. This produces shorter, more elegant statements, for instance:
disp(sprintf('The new values of x and y are %d and %d respectively', x, y))
You can control how variables are displayed using the format specifiers. For instance, if x is not necessarily an integer, you can use %.4f, for example, instead of %d.
EDIT: like Jonas pointed out, you can also use fprintf(...) instead of disp(sprintf(...)).
Try:
disp(['The new values of x and y are ', num2str(x), ' and ', num2str(y), ', respectively']);
You can actually omit the commas too, but IMHO they make the code more readable.
By the way, what I've done here is concatenated 5 strings together to form one string, and then fed that single string into the disp function. Notice that I essentially concatenated the string using the same syntax as you might use with numerical matrices, ie [x, y, z]. The reason I can do this is that matlab stores character strings internally AS numeric row vectors, with each character denoting an element. Thus the above operation is essentially concatenating 5 numeric row vectors horizontally!
One further point: Your code failed because matlab treated your num2str(x) as a string and not as a function. After all, you might legitimately want to print "num2str(x)", rather than evaluate this using a function call. In my code, the first, third and fifth strings are defined as strings, while the second and fourth are functions which evaluate to strings.