how can I check if a string is a positive integer? - c#

I mean :
1231 YES
121.1241 NO
121,1241 NO
-121 NO
124a NO
how can i do it faster in C#?

int x;
if (int.TryParse(str, out x) && x > 0)

You can check if it only contains digits:
if (theString.All(Char.IsDigit))

An alternative to actually parsing it is to check if the string is non-empty and only contains digits, optionally with a leading + sign if you want to allow that.
Note that this won't perform any range checking - so 9999999999999999999999999999999999 would be valid, even though it wouldn't fit into an int or a long.
You could use a regex for that, or possibly LINQ:
var nonNegative = text.Length > 0 && text.All(c => c >= '0' && c <= '9');
(This is similar to Guffa's Char.IsDigit approach, but restricts itself to ASCII digits. There are numerous non-ASCII digits in Unicode.)
Note that this will restrict it to non-negative values - not just positive values. How would you want to treat "0" and "0000"?

Related

What's the meaning of Array[string[i] - 'a'] in C#? [duplicate]

This question already has answers here:
Java: Subtract '0' from char to get an int... why does this work?
(10 answers)
How does subtracting the character '0' from a char change it into an int?
(4 answers)
Closed 8 years ago.
I’m learning Java through "introduction to Java programming 9th edition" by Daniel Liang at chapter 9 "strings" I’ve encountered this piece of code :
public static int hexCharToDecimal(char ch) {
if (ch >= 'A' && ch <= 'F')
return 10 + ch - 'A';
else
return ch - '0';
}
Can someone explain what just happened in here? How is possible to add/subtract chars from integers and what's the meaning behind it?
From the Docs
The char data type is a single 16-bit Unicode character.
A char is represented by its code point value:
min '\u0000' (or 0)
max: '\uffff' (or 65,535)
You can see all of the English alphabetic code points on an ASCII table.
Note that 0 == \u0000 and 65,535 == \uffff, as well as everything in between. They are corresponding values.
A char is actually just stored as a number (its code point value). We have syntax to represent characters like char c = 'A';, but it's equivalent to char c = 65; and 'A' == 65 is true.
So in your code, the chars are being represented by their decimal values to do arithmetic (whole numbers from 0 to 65,535).
For example, the char 'A' is represented by its code point 65 (decimal value in ASCII table):
System.out.print('A'); // prints A
System.out.print((int)('A')); // prints 65 because you casted it to an int
As a note, a short is a 16-bit signed integer, so even though a char is also 16-bits, the maximum integer value of a char (65,535) exceeds the maximum integer value of a short (32,767). Therefore, a cast to (short) from a char cannot always work. And the minimum integer value of a char is 0, whereas the minimum integer value of a short is -32,768.
For your code, let's say that the char was 'D'. Note that 'D' == 68 since its code point is 68.
return 10 + ch - 'A';
This returns 10 + 68 - 65, so it will return 13.
Now let's say the char was 'Q' == 81.
if (ch >= 'A' && ch <= 'F')
This is false since 'Q' > 'F' (81 > 70), so it would go into the else block and execute:
return ch - '0';
This returns 81 - 48 so it will return 33.
Your function returns an int type, but if it were to instead return a char or have the int casted to a char afterward, then the value 33 returned would represent the '!' character, since 33 is its code point value. Look up the character in ASCII table or Unicode table to verify that '!' == 33 (compare decimal values).
This is because char is a primitive type which can be used as a numerical value. Every character in a string is encoded as a specific number (not entirely true in all cases, but good enough for a basic understanding of the matter) and Java allows you to use chars in such a way.
It probably allows this mostly for historical reasons, this is how it worked in C and they probably motivated it with "performance" or something like that.
If you think it's weird then don't worry, I think so too
The other answer is incorrect actually. ASCII is a specific encoding (an encoding is some specification that says "1 = A, 2 = B, ... , 255 = Space") and that is not the one used in Java. A Java char is two bytes wide and is interpreted through the unicode character encoding.
Chars are in turn stored as integers(ASCII value) so that you can perform add and sub on integers which will return ASCII value of a char
Regardless of how Java actually stores the char datatype, what's certain is this, the character 'A' subtracted from the character 'A' would be represented as the null character, \0. In memory, this means every bit is 0. The size in memory a char takes up in memory may vary from language to language, but as far as I know, the null character is the same in all the languages, every bit is equal to 0.
As an int value, a piece of memory with every bit equal to 0 represents the integer value of 0.
And as it turns out, when you do "character math", subtracting any alphabetical character from any other alphabetical character (of the same case) results in bits being flipped in such a way that, if you were to interpret them as an int, would represent the distance between these characters. Additionally, subtracting the char '0' from any other numeric char will result in int value of the char you subtracted from, for basically the same reason.
'A' - 'A' = '\0'
'a' - 'a' = '\0'
'0' - '0' = '\0'

trying to find the biggest negative and smallest positive from given input

im trying to build an algorythm which input is 10 numbers (positive and negative) and the output is the smallest positive number and the biggest negative number.
im getting the right answer for the smallest positive, but not for the biggest negative.
code and output are inserted.
If you have a collection, say, int[] numbers you can just query it with a help of Linq:
using System.Linq;
...
int[] numbers = ...
...
// Either biggest negative or 0 (if we don't have any negative values)
int biggestNegative = numbers
.Where(x => x < 0)
.DefaultIfEmpty() // <- we don't want exception on empty input
.Max();
// Either smallest positive or 0 (if we don't have any positive values)
int smallestPositive = numbers
.Where(x => x > 0)
.DefaultIfEmpty() // <- we don't want exception on empty input
.Min();
If you prefer to compute the values in a for loop:
int biggestNegative = 0;
int smallestPositive = 0;
for (int i = 0; i < 10; ++i) {
...
// Simplest, you may want to check user input
int value = int.Parse(Console.ReadLine());
...
if (value > 0)
smallestPositive = smallestPositive == 0
? value
: Math.Min(smallestPositive, value);
else if (value < 0)
biggestNegative = biggestNegative == 0
? value
: Math.Max(biggestNegativee, value);
}
Let's print the values out:
Console.WriteLine(
$"Biggest negative: {(biggestNegative == 0 ? "???" : biggestNegative.ToString())}");
Console.WriteLine(
$"Smallest positive: {(smallestPositive == 0 ? "???" : smallestPositive.ToString())}");
if (num>negMax)
There is a mistake in this condition. As your initial negMax value is 0, no negative number will meet the condition, and therefore negMax value will never be updated.
You're initializing negMax as 0.
There is no negative number that is bigger than 0.
Depending on what exactly you want to accomplish, you could do one of the following:
Initialize negMax as int.MinValue
This would be okay if it's guaranteed that there's at least one negative number, since the first negative input is guaranteed to be equal or greater. If negative input isn't guaranteed, you cannot tell if there were any and your output may end up incorrect.
Modify the condition for assigning a new value to negMax
You could instead modify the condition for assigning a new value to negMax to if (num > negMax || negMax >= 0).
Since you usually don't treat 0 as a negative number (and if you do, you can initialize negMax with any positive number instead), you'd know that there were no negative numbers if the output ends up as 0.
To do the same with posMin, you'd have to initialize it as something less than 0 and adjust the if-condition for assigning a value to that variable accordingly.
Alternatively, you could also declare negMax and posMin as int?s and check for null instead of >= 0.
If you choose this way, you can check the values for both variables and output, for example, that no negative or no positive numbers were entered instead of outputting whichever placeholder you chose.

Regex Pattern number1 to number2

I'm searching for a pattern for the following behavior:
number1-number2
number1: Can be everything >= 0 and <= int.MaxValue
number2: Can be everything >= number1 and <= int.MaxValue
e.g.
"1-2" => True
"0-0" => True
"10-22" => True
"22-10" => False
"10-10" => True
"a-b" => False
It would be also nice if I could directly extract the two int values.
You cannot use a regex for comparing extracted numbers. You need to parse the values with int.TryParse and implement other checks to get what you need.
Assuming you only have integer positive numbers in the ranges, here is a String.Split and int.TryParse approach:
private bool CheckMyRange(string number_range, ref int n1, ref int n2)
{
var rng = number_range.Split('-');
if (rng.GetLength(0) != 2)
return false;
if (!int.TryParse(rng[0], out n1))
return false;
if (!int.TryParse(rng[1], out n2))
return false;
if (n1 >= 0 && n1 <= int.MaxValue)
if (n2 >= n1 && n2 <= int.MaxValue)
return true;
return false;
}
And call it like
int n1 = -1;
int n2 = -1;
bool result = CheckMyRange("1-2", ref n1, ref n2);
Solution
It is possible to test it using regex - but you should prefer a solution in code because it will be much faster. This regex needs a lot of backtracking. The only advantage of this regex is that it works for an arbitrary number length.
(?:^0+-\d+$)
|
(?:^(?>0*)(?<number>\d+)-(?>0*)\k<number>$)
|
(?:
(?:^(?>0*)(?<length>\d)+-(?>0*)(?<-length>\d)*(?(length)(?!))\d+$)
|
(
(?=^(?>0*)(?<o>\d)+-(?>0*)(?<-o>\d)*(?(o)(?!))$)
^
(?>0*)
(?<prefix>\d*)
(?:(?<g0>0)|(?<g1>1)|(?<g2>2)|(?<g3>3)|(?<g4>4)|(?<g5>5)|(?<g6>6)|(?<g7>7)|(?<g8>8)|(?<g9>9))
\d*
-
(?>0*)
\k<prefix>
(?(g0)[1-9]|(?(g1)[2-9]|(?(g2)[3-9]|(?(g3)[4-9]|(?(g4)[5-9]|(?(g5)[6-9]|(?(g6)[7-9]|(?(g7)[89]|(?(g8)9|(?!))))))))))
\d*
$
)
)
This matches for every x-y where x <= y for positive integer numbers including leeding zeros.
DEMO
It doesn't work for chars.
Explanation
I was able to create a regex that matches x-y for all x < y. The question was x <= y. So I splitted the question to x = y | x < y.
We need to handle that the first or both numbers does only contain zeros but that's trivial:
^0+-\d+$
Now the case x = y
^(?>0*)(?<number>\d+)-(?>0*)\k<number>$
The tricky part is x < y.
x is smaller than y if x is shorter in char length than y (leeding zeros are captured by an atomic group):
^(?>0*)(?<length>\d)+-(?>0*)(?<-length>\d)*(?(length)(?!))\d+
This first group captures the whole number by one capture per digit. After the separator a balancing group definition clears the capture stack and forces at least one more digit.
Both numbers are of the same length (if the first number is longer it is also greater and should not match).
To ensure that both numbers are of the same length I started with a positive look behind assertion that ensures it the same way I tested for a longer number in step 1:
(?=^(?>0*)(?<o>\d)+-(?>0*)(?<-o>\d)*(?(o)(?!))$)
After that the algorithm is simple. Start at the beginning. If the current digit is equal go to the next digit. If the current x-digit is slower than the current y-digit we're finished and a match is found. If it's slower we should not match. This is done by that pattern:
^
(?>0*) # cut out leeding zeros
(?<prefix>\d*)
.*
-
(?>0*) # cut out leeding zeros
\k<prefix> # both numbers start with the same part
.*
$
And now the check for one digit. There are only 10 possibilities [0-9]. Each of them is captures by a single group:
(?<g0>0)|(?<g1>1)|(?<g2>2)|(?<g3>3)|(?<g4>4)|(?<g5>5)|(?<g6>6)|(?<g7>7)|(?<g8>8)|(?<g9>9)
Now we're able to use conditions to check whether the current y-digit is greater then the current x-digit. Lets show for 0 and 1:
(?<g0>0)|(?<g1>1): If a 0 matches for the current x-digit there are only [1-9] for the current y-digit. If 1 matches only [2-9] is able. This could be used in a condition:
(?(g0)[1-9]|...) what means if g0 has a capture [1-9] has to match otherwise the rest has to match. This is combined to:
(?(g0)[1-9]|(?(g1)[2-9]|(?(g2)[3-9]|(?(g3)[4-9]|(?(g4)[5-9]|(?(g5)[6-9]|(?(g6)[7-9]|(?(g7)[89]|(?(g8)9|(?!))))))))))
The last trick is that none of the groups g[0-8] has been matched only g9 is available and there is no greater digit possible and the match should fail (?!).
This all has been combined to the whole regex that matches x-y for all x <= y.
Regex can only be used to match the numbers. Post that a comparison operation needs to be done.
string num="number1-number2";//where (number1 & number2)=numeric val
MatchCollection stringVal= Regex.Matches(num,#"\d+");
int num1=Convert.ToInt32(stringVal[0].Value);
int num2=Convert.ToInt32(stringVal[1].Value);
if(num1>=0 && num1<=int.MaxValue && num2>=num1 && num2<=int.MaxValue)
return true;
else
return false;
will give you an array containing the the numbers

C#, negative decimal values to heximal

I'm writing a code which has to save up as much space as possible.
for (int i = 0; i < Code.Length; i++){
CodeInHex[i] = String.Format("{0:X}", Code[i]); // e.g. Dec value = -95, hex = "FFFFFFA1"
}
Is there a way to make heximal value equal to -A1 instead of "FFFFFFA1"? (saw it is allowed in c# here).
Well, you could do it manually:
var val = Code[i];
CodeInHex[i] = val < 0 ? ("-" + (-val).ToString("X")) : val.ToString("X");
But! Negative hex is not a common way of representing negative numbers. It is only "allowed in C#" because it is the unary negation operator applied to a positive constant; i.e. when the question shows -0x1, it is "negate (some expression)", where "some expression" is 0x1.

How to check input double value contain how many digits?

I need a double value to contain 2 digits after ".", such as 2.15, 20.15. If the input value is 3.125, then it should print an error message.
My code is:
private static bool isTwoDigits(double num)
{
return (num - Math.Floor(num)).ToString().Length <= 4;
}
If you input 2.15, then it will be 2.15 -2 = 0.15 <= 4 - which works. But when I change num to 20.15 it doesn't, because (num - Math.Floor(num)) here will return 0.14999999999.
Any other good ideas?
This is the nature of binary floating points number. Just like 1/3 can't be exactly written out as a finite decimal number, 0.1 can't be exactly represented by a finite binary expansion.
So depending on what you are trying to achieve exactly, you could:
If you are validating some string input (e.g. a textbox), you can process the information at the string level, e.g. with a RegEx.
You can store your numbers in the decimal datatype, which can store decimal values exactly.
You can do your computation on a double but you have to give yourself a tolerance. If you expect only 2 digits of precision, you can do something like Math.Abs(x - Math.Round(x, 2)) < 0.00000001). The definition of this tolerance margin depends on your use case.
If you're really worried about the number of decimal places, on a base-10 number, use decimal instead of double.
the decimal is for calculating financial calculations, and the reason it's called decimal in the first place is so that it can better handle base-10 calculations such as dollars and cents.
And you can also check if the number is 2 digits a bit more simply.
return num % 0.01m == 0.0m;
SO as has already been said, you can use regexp to ensure the entire format is correct.
But if you know there will only be 1 decimal because its already a number you can also just use String.IndexOf
eg
double foo = .... ;
string fooString = foo.ToString();
if (fooString.Length - fooString.IndexOf(".") != 3) => error.
(Its 3 because Length is max index + 1 )

Categories

Resources