I need to determine if a string contains just an integer. The built-in function isinteger is not working.
To avoid loops I'd like to apply this task on cell arrays of strings.
For example:
Q = { 'qf5' ; '4' ; 'true' ; 'false' ; '4.00' ; '4E0' ; '4e0' ; '657' };
desired result:
integers = 0 1 0 0 0 0 0 1
For a single string I figured out an ugly workaround, but I can't imagine that this is the only possible way, and also it requires a loop to use it on cell arrays:
myString = '4';
integer = uint64( str2double( myString ) );
newString = int2str( integer );
isStringInteger = strcmp(newString,myString);
Which essential function am I missing?
You can do it with regexp; and to avoid the loop you use cellfun:
~cellfun('isempty', regexp(Q, '^-?\d+$'))
This considers an "integer" as a string of digits, possibly with one minus sign at the beginning.
Note that cellfun with the builtin function 'isempty' is very fast.
Well, the string is not an integer, therefore the question as such is not correct. What you want to check is whether the string is a representation of an integer. The isinteger function is also not what you want, because it does not check whether the actual content of a numeric variable is an integer, but whether the data type is an integer type.
As far as I can tell, there is no built-in way to check whether a string represents an integer. One approach to implement such a check would be to see whether all the characters in the string represent digits:
isintstr = all(myString >= '0') && all(myString <= '9')
This code takes advantage of the fact that the decimal digits are encoded in sequence in ASCII and Unicode.
To allow for leading and trailing white space, use
isintstr = all(strtrim(myString) >= '0') && all(strtrim(myString) <= '9')
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'
String to Integer (atoi)
This problem is implement atoi to convert a string to an integer.
When test input = " +0 123"
My code return = 123
But why expected answer = 0?
======================
And if test input = " +0123"
My code return = 123
Now expected answer = 123
So is that answer wrong?
I think this is expected result as it said
Requirements for atoi:
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
Your first test case has a space in between two different digit groups, and atoi only consider the first group which is '0' and convert into integer
For some reason in
size(strfind(n,','))
the number 44 is special and produces a comma found result:
value={55}
numCommas = size(strfind(value{1},','),2)
ans= 0 ...(GOOD)
value={44}
numCommas = size(strfind(value{1},','),2)
ans= 1 ...(BAD) - Why is it doing this?
value={'44,44,44'}
numCommas = size(strfind(value{1},','),2)
ans= 2 ...(GREAT)
I need to find the number of commas in a cell element, where the element can either be an integer or a string.
To elaborate on my comment. The ASCII code for a comma, (,), is 44. Effectively what you are doing in your code is
size(strfind(44,','),2)
or
size(strfind(char(44),','),2)
where 44 is not a string but is interpreted as a numeric value which is then converted to a character and results in a comma, (,) which we can see when we use char
>> char(44)
ans =
,
You can fix your code by changing
value={44}
to
value={'44'}
so then you will be performing strfind on a string instead of a numeric value.
>> size(strfind('44', ','), 2)
ans =
0
which provides the correct answer.
Alternatively you could use num2str
>> size(strfind(num2str(value{1}), ','), 2)
ans =
0
You can avoid this by simply doing value{1} = '44'. Or if that's not an alternative, use num2str like this:
value={44};
numCommas = size(strfind(num2str(value{1}),','),2)
numCommas =
0
This will also work for string inputs:
value={'44,44,44'};
numCommas = size(strfind(num2str(value{1}),','),2)
numCommas =
2
Why do you get "wrong" results?`
It's because 44 is the ASCII code for comma ,.
You can check this quite simply by casting the value to char.
char(44)
ans =
,
You are checking for commas in a string. As the input to strfind is an integer, it automatically cast it to char. In the last example, your are inserting a "real" string, thus it finds the two commas in there.
Try this one:
value={'44'}
numCommas = size(strfind(value{1},','),2)
instead of:
value={44}
numCommas = size(strfind(value{1},','),2)
It should work, since it's a char now.
I'm trying to get a 0 or 1 in a value for true/false. Here's the code:
use strict;
my %h = (Y => "y");
my $bool_x = 1 & exists $h{X};
my $bool_y = 1 & exists $h{Y};
print("x $bool_x y $bool_y\n");
I needed to add the "1 &" to force it to not be the empty string. Is there a better way to do this? I realize that it's an artifact of the way perl prints the false value, but I need it to be a 0 not the empty string.
The most efficient way to do this is just:
$bool || 0
Your code is far from clear. The & operator is a bitwise operator that behaves differently on numbers and strings, but exists returns a value that will obligingly be the number zero or the empty string depending on what is required of it. perldoc perlop has this to say
Although no warning is currently raised, the result is not well defined when this operation is performed on operands that aren't either numbers (see Integer Arithmetic) nor bitstrings (see Bitwise String Operators)
So because the result of exists is one such value your code is on shakey ground
There is no need to write something arcane, and if you want to represent Perl's internal true and false values by a different pair of values then the conditional operator is the correct choice
my $bool_x = exists $h{X} ? 1 : 0
I believe that's the most readable without being verbose, and that's all that matters here. It's also applicable to any other pair of values that you may choose, such as
my $bool_x = exists $h{X} ? 'Y' : 'N'
There are many ways to "numify" a true/false value.
If $var can contain 1 or any false value, all of these will evaluate to either "0" or "1":
0 + $var
0 | $var
$var || 0
1 * $var
1 & $var (you discovered this one, already)
chr(48+$var)
sprintf "%d", $var
These constructions return a 0/1 value when $var can contain any true or false value:
0 + !!$var ( !! true => 1, !! false => "" )
1 - !$var
$var ? 1 : 0
i donot know why there is error in this coding:
hex_str1 = '5'
bin_str1 = dec2bin(hex2dec(hex_str1))
hex_str2 = '4'
bin_str2 = dec2bin(hex2dec(hex_str2))
c=xor(bin_str1,bin_str2)
the value of c is not correct when i transform the hex to binary by using the xor function.but when i used the array the value of c is correct.the coding is
e=[1 1 1 0];
f=[1 0 1 0];
g=xor(e,f)
what are the mistake in my first coding to xor of hec to binary value??anyone can help me find the solution...
Your mistake is applying xor on two strings instead of actual numerical arrays.
For the xor command, logical "0"s are represented by actual zero elements. Any non-zero elements are interpreted as logical "1"s.
When you apply xor on two strings, the numerical value of each character (element) is its ASCII value. From xor's point of view, the zeroes in your string are not really zeroes, but simply non-zero values (being equal to the ASCII value of the character '0'), which are interpreted as logical "1"s. The bottom line is that in your example you're xor-ing 111b and 111b, and so the result is 0.
The solution is to convert your strings to logical arrays:
num1 = (bin_str1 == '1');
num2 = (bin_str2 == '1');
c = xor(num1, num2);
To convert the result back into a string (of a binary number), use this:
bin_str3 = sprintf('%d', c);
... and to a hexadecimal string, add this:
hex_str3 = dec2hex(bin2dec(bin_str3));
it is really helpful, and give me the correct conversion while forming HMAC value in matlab...
but in matlab you can not convert string of length more than 52 character using bin2dec() function and similarly hex2dec() can not take hexadecimal character string more than 13 length.