I have a question on the following line on a MATLAB script. What does '%2.2g' mean in this line? I know it is use to format a number notation. Are there other options as to changing it to a 10^1, 10^2, 10^3? Can anyone find some resources for me to read?
num2str((rng'* (sp(t)-sa(t))) + sa(t),'%2.2g')
%a.bg :
a: stands for the width of the number
b: the number of decimals printed.
g: chooses the more compact of %e or %f. (Insignificant zeroes do not print.)
For example:
>> sprintf('%2.2g', 1.23)
ans =
1.2
>> sprintf('%2.2g', 123000)
ans =
1.2e+05
Note that it rounds the result.
For exponential notation just use something %2.2e.
For formatting rules just look at the documentation: Formatting Text- Matlab
Related
I'd like to know how regexp is used for floating numbers or is there any other function to do this.
For example, the following returns {'2', '5'} rather than {'2.5'}.
nums= regexp('2.5','\d+','match')
Regular expressions are a tool for low-level text parsing and they have no concept of numeric datatypes. If you will want to parse decimals, you need to consider what characters compose a decimal number and design a regexp to explicitly match all of those characters.
Your example only returns the '2' and '5' because your pattern only matches characters that are digits (\d). To handle the decimal numbers, you need to explicitly include the . in your pattern. The following will match any number of digits followed by 0 or 1 radix points and 0 or more numbers after the radix point.
regexp('2.5', '\d+\.?\d*', 'match')
This assumes that you'll always have a leading digit (i.e. not '.5')
Alternately, you may consider using something like textscan or sscanf instead to parse your string which is going to be more robust than a custom regex since they are aware of different numeric datatypes.
C = textscan('2.5', '%f');
C = sscanf('2.5', '%f');
If your string only contains this floating point number, you can just use str2double
val = str2double('2.5');
#Suever answer has already been accepted, anyway here is some more complete one that should accept all sorts of floating points syntaxes (including NaN and +/-Inf by default):
% Regular expression for capturing a double value
function [s] = cdouble(supportPositiveInfinity, supportNegativeInfinity,
supportNotANumber)
%[
if (nargin < 3), supportNotANumber = true; end
if (nargin < 2), supportNegativeInfinity = true; end
if (nargin < 1), supportPositiveInfinity = true; end
% A double
s = '[+\-]?(?:(?:\d+\.\d*)|(?:\.\d+)|(?:\d+))(?:[eE][+\-]?\d+)?'; %% This means a numeric double
% Extra for nan or [+/-]inf
extra = '';
if (supportNotANumber), extra = ['nan|' extra]; end
if (supportNegativeInfinity), extra = ['-inf|' extra]; end
if (supportPositiveInfinity), extra = ['inf|\+inf|' extra]; end
% Adding capture
if (~isempty(extra))
s = ['((?i)(?:', extra, s, '))']; % (?i) => Locally case-insensitive for captured group
else
s = ['(', s, ')'];
end
%]
end
Basically above pattern says:
Eventually start with '+' or '-' sign
Then followed by either
One or more digits followed by a dot and eventually zero to many digits
A dot followed by one or more digits
One or more digits only
Then followed by exponant pattern, that is:
'e' or 'E' (eventually followed with '+' or '-') and one or more digits
Pattern is later completed with support of Inf, +Inf, -Inf and NaN in case insensitive way. Finally everthing is enclosed between ( and ) for capturing purpose.
Here is some online test example: https://regex101.com/r/K87z6e/1
Or you can test in matlab:
>> regexp('Hello 1.235 how .2e-7 are INF you +.7 doing ?', cdouble(), 'match')
ans =
'1.235' '.2e-7' 'INF' '+.7'
I'd like to have a function generate(n) that generates the first n lowercase characters of the alphabet appended in a string (therefore: 1<=n<=26)
For example:
generate(3) --> 'abc'
generate(5) --> 'abcde'
generate(9) --> 'abcdefghi'
I'm new to Matlab and I'd be happy if someone could show me an approach of how to write the function. For sure this will involve doing arithmetic with the ASCII-codes of the characters - but I've no idea how to do this and which types that Matlab provides to do this.
I would rely on ASCII codes for this. You can convert an integer to a character using char.
So for example if we want an "e", we could look up the ASCII code for "e" (101) and write:
char(101)
'e'
This also works for arrays:
char([101, 102])
'ef'
The nice thing in your case is that in ASCII, the lowercase letters are all the numbers between 97 ("a") and 122 ("z"). Thus the following code works by taking ASCII "a" (97) and creating an array of length n starting at 97. These numbers are then converted using char to strings. As an added bonus, the version below ensures that the array can only go to 122 (ASCII for "z").
function output = generate(n)
output = char(97:min(96 + n, 122));
end
Note: For the upper limit we use 96 + n because if n were 1, then we want 97:97 rather than 97:98 as the second would return "ab". This could be written as 97:(97 + n - 1) but the way I've written it, I've simply pulled the "-1" into the constant.
You could also make this a simple anonymous function.
generate = #(n)char(97:min(96 + n, 122));
generate(3)
'abc'
To write the most portable and robust code, I would probably not want those hard-coded ASCII codes, so I would use something like the following:
output = 'a':char(min('a' + n - 1, 'z'));
...or, you can just generate the entire alphabet and take the part you want:
function str = generate(n)
alphabet = 'a':'z';
str = alphabet(1:n);
end
Note that this will fail with an index out of bounds error for n > 26, so you might want to check for that.
You can use the char built-in function which converts an interger value (or array) into a character array.
EDIT
Bug fixed (ref. Suever's comment)
function [str]=generate(n)
a=97;
% str=char(a:a+n)
str=char(a:a+n-1)
Hope this helps.
Qapla'
I want to use fscanf for reading a text file containing 4 rows with an unknown number of columns. The newline is represented by two consecutive spaces.
It was suggested that I pass : as the sizeA parameter but it doesn't work.
How can I read in my data?
update: The file format is
String1 String2 String3
10 20 30
a b c
1 2 3
I have to fill 4 arrays, one for each row.
See if this will work for your application.
fid1=fopen('test.txt');
i=1;
check=0;
while check~=1
str=fscanf(fid1,'%s',1);
if strcmp(str,'')~=1;
string(i)={str};
end
i=i+1;
check=strcmp(str,'');
end
fclose(fid1);
X=reshape(string,[],4);
ar1=X(:,1)
ar2=X(:,2)
ar3=X(:,3)
ar4=X(:,4)
Once you have 'ar1','ar2','ar3','ar4' you can parse them however you want.
I have found a solution, i don't know if it is the only one but it works fine:
A=fscanf(fid,'%[^\n] *\n')
B=sscanf(A,'%c ')
Z=fscanf(fid,'%[^\n] *\n')
C=sscanf(Z,'%d')
....
You could use
rawText = getl(fid);
lines = regexp(thisLine,' ','split);
tokens = {};
for ix = 1:numel(lines)
tokens{end+1} = regexp(lines{ix},' ','split'};
end
This will give you a cell array of strings having the row and column shape or your original data.
To read an arbitrary line of text then break it up according the the formating information you have available. My example uses a single space character.
This uses regular expressions to define the separator. Regular expressions powerful but too complex to describe here. See the MATLAB help for regexp and regular expressions.
I'm fairly new to Matlab, although not to programming. I'm trying to hash a string, and get back a single value that acts as a unique id for that string. I'm using this DataHash function from FileExchange which returns the hash as an integer vector. So far the best solution I've found for converting this to a single numeric value goes:
hash_opts.Format = 'uint8';
hash_vector = DataHash(string, hash_opts);
hash_string = num2str(hash_vector);
% Use a simple regex to remove all whitespace from the string,
% takes it from '1 2 3 4' to '1234'
hash_string = regexprep(hash_string, '[\s]', '');
hashcode = str2double(hash_string);
A reproducible example that doesn't depend on DataHash:
hash_vector = [1, 23, 4, 567];
hash_string = num2str(hash_vector);
% Use a simple regex to remove all whitespace from the string,
% takes it from '1 2 3 4' to '1234'
hash_string = regexprep(hash_string, '[\s]', '');
hashcode = str2double(hash_string); % Output: 1234567
Are there more efficient ways of achieving this, without resorting to a regex?
Yes, Matlab's regex implementation isn't particularly fast. I suggest that you use strrep:
hashcode = str2double(strrep(hash_string,' ',''));
Alternatively, you can use a string creation method that doesn't insert spaces in the first place:
hash_vector = [1, 23, 4, 567];
hash_string = str2double(sprintf('%d',hash_vector))
Just make sure that your hash number is less than 2^53 or the conversion to double might not be exact.
I'v seen there's already an answer - though it loses precission as it omits leading 0s - I'm not really sure if it will cause you troubles but I wouldn't want to rely on it.
As you output as uint8 why don't you use hex values instead - this will give you the exactly same number. Converting back is also easy using dec2hex.
hash_vector = [1, 23, 4, 253]
hash_str=sprintf('%02x',hash_vector); % to assure every 8 bit use 2 hex digits!
hash_dig=hex2dec(hash_str)
btw. - your sampe hash contains 567 - an impossible number in uint8.
Having looked at DataHash the question would also be why not use base64 or hex in the first place.
I think it's a simple question. I want:
a = 1.154648126486416;
to become:
a = 1.154;
and not:
a = 1.15000000000;
How do I do that without using format('bank').
You could do this:
a = floor(a*1000)/1000;
Building on #gnovice's answer, you can format the output as a string to get rid of the extra zeros. See the sprintf documentation for all the formatting options.
str=sprintf('The result is %1.3f.',a);
disp(str)
will show "The result is 1.154." in the command prompt. Or write the string to file, etc., etc.
a = 1.154648126486416;
% desired precision
b = -3;
% your answer
ans = floor(a*10^(-b))/(10^(-b));
The answer is 1.1540
this is good if you don't care about the rest of digits but if you do care then you just have to simply change "floor" to "round".
ans = round(a*10^(-b))/(10^(-b));
The answer is 1.1550