Convert char to int in C# - c#

I have a char in c#:
char foo = '2';
Now I want to get the 2 into an int. I find that Convert.ToInt32 returns the actual decimal value of the char and not the number 2. The following will work:
int bar = Convert.ToInt32(new string(foo, 1));
int.parse only works on strings as well.
Is there no native function in C# to go from a char to int without making it a string? I know this is trivial but it just seems odd that there's nothing native to directly make the conversion.

This will convert it to an int:
char foo = '2';
int bar = foo - '0';
This works because each character is internally represented by a number. The characters '0' to '9' are represented by consecutive numbers, so finding the difference between the characters '0' and '2' results in the number 2.

Interesting answers but the docs say differently:
Use the GetNumericValue methods to
convert a Char object that represents
a number to a numeric value type. Use
Parse and TryParse to convert a
character in a string into a Char
object. Use ToString to convert a Char
object to a String object.
http://msdn.microsoft.com/en-us/library/system.char.aspx

Has anyone considered using int.Parse() and int.TryParse() like this
int bar = int.Parse(foo.ToString());
Even better like this
int bar;
if (!int.TryParse(foo.ToString(), out bar))
{
//Do something to correct the problem
}
It's a lot safer and less error prone

char c = '1';
int i = (int)(c - '0');
and you can create a static method out of it:
static int ToInt(this char c)
{
return (int)(c - '0');
}

Try This
char x = '9'; // '9' = ASCII 57
int b = x - '0'; //That is '9' - '0' = 57 - 48 = 9

By default you use UNICODE so I suggest using faulty's method
int bar = int.Parse(foo.ToString());
Even though the numeric values under are the same for digits and basic Latin chars.

This converts to an integer and handles unicode
CharUnicodeInfo.GetDecimalDigitValue('2')
You can read more here.

The real way is:
int theNameOfYourInt = (int).Char.GetNumericValue(theNameOfYourChar);
"theNameOfYourInt" - the int you want your char to be transformed to.
"theNameOfYourChar" - The Char you want to be used so it will be transformed into an int.
Leave everything else be.

Principle:
char foo = '2';
int bar = foo & 15;
The binary of the ASCII charecters 0-9 is:
0   -   0011 0000
1   -   0011 0001
2   -   0011 0010
3   -   0011 0011
4   -   0011 0100
5   -   0011 0101
6   -   0011 0110
7   -   0011 0111
8   -   0011 1000
9   -   0011 1001
and if you take in each one of them the first 4 LSB (using bitwise AND with 8'b00001111 that equals to 15) you get the actual number (0000 = 0,0001=1,0010=2,... )
Usage:
public static int CharToInt(char c)
{
return 0b0000_1111 & (byte) c;
}

I am agree with #Chad Grant
Also right if you convert to string then you can use that value as numeric as said in the question
int bar = Convert.ToInt32(new string(foo, 1)); // => gives bar=2
I tried to create a more simple and understandable example
char v = '1';
int vv = (int)char.GetNumericValue(v);
char.GetNumericValue(v) returns as double and converts to (int)
More Advenced usage as an array
int[] values = "41234".ToArray().Select(c=> (int)char.GetNumericValue(c)).ToArray();

First convert the character to a string and then convert to integer.
var character = '1';
var integerValue = int.Parse(character.ToString());

I'm using Compact Framework 3.5, and not has a "char.Parse" method.
I think is not bad to use the Convert class. (See CLR via C#, Jeffrey Richter)
char letterA = Convert.ToChar(65);
Console.WriteLine(letterA);
letterA = 'あ';
ushort valueA = Convert.ToUInt16(letterA);
Console.WriteLine(valueA);
char japaneseA = Convert.ToChar(valueA);
Console.WriteLine(japaneseA);
Works with ASCII char or Unicode char

Comparison of some of the methods based on the result when the character is not an ASCII digit:
char c1 = (char)('0' - 1), c2 = (char)('9' + 1);
Debug.Print($"{c1 & 15}, {c2 & 15}"); // 15, 10
Debug.Print($"{c1 ^ '0'}, {c2 ^ '0'}"); // 31, 10
Debug.Print($"{c1 - '0'}, {c2 - '0'}"); // -1, 10
Debug.Print($"{(uint)c1 - '0'}, {(uint)c2 - '0'}"); // 4294967295, 10
Debug.Print($"{char.GetNumericValue(c1)}, {char.GetNumericValue(c2)}"); // -1, -1

I was searched for the most optimized method and was very surprized that the best is the easiest (and the most popular answer):
public static int ToIntT(this char c) =>
c is >= '0' and <= '9'?
c-'0' : -1;
There a list of methods I tried:
c-'0' //current
switch //about 25% slower, no method with disabled isnum check (it is but performance is same as with enabled)
0b0000_1111 & (byte) c; //same speed
Uri.FromHex(c) /*2 times slower; about 20% slower if use my isnum check*/ (c is >= '0' and <= '9') /*instead of*/ Uri.IsHexDigit(testChar)
(int)char.GetNumericValue(c); // about 20% slower. I expected it will be much more slower.
Convert.ToInt32(new string(c, 1)) //3-4 times slower
Note that isnum check (2nd line in the first codeblock) takes ~30% of perfomance, so you should take it off if you sure that c is char. The testing error was ~5%

Use this:
public static string NormalizeNumbers(this string text)
{
if (string.IsNullOrWhiteSpace(text)) return text;
string normalized = text;
char[] allNumbers = text.Where(char.IsNumber).Distinct().ToArray();
foreach (char ch in allNumbers)
{
char equalNumber = char.Parse(char.GetNumericValue(ch).ToString("N0"));
normalized = normalized.Replace(ch, equalNumber);
}
return normalized;
}

One very quick simple way just to convert chars 0-9 to integers:
C# treats a char value much like an integer.
char c = '7'; (ascii code 55) int x = c - 48; (result = integer of 7)

Use Uri.FromHex.
And to avoid exceptions Uri.IsHexDigit.
char testChar = 'e';
int result = Uri.IsHexDigit(testChar)
? Uri.FromHex(testChar)
: -1;

I prefer the switch method.
The performance is the same as c - '0' but I find the switch easier to read.
Benchmark:
Method
Mean
Error
StdDev
Allocated Memory/Op
CharMinus0
90.24 us
7.1120 us
0.3898 us
39.18 KB
CharSwitch
90.54 us
0.9319 us
0.0511 us
39.18 KB
Code:
public static int CharSwitch(this char c, int defaultvalue = 0) {
switch (c) {
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
default: return defaultvalue;
}
}
public static int CharMinus0(this char c, int defaultvalue = 0) {
return c >= '0' && c <= '9' ? c - '0' : defaultvalue;
}

This worked for me:
int bar = int.Parse("" + foo);

I've seen many answers but they seem confusing to me. Can't we just simply use Type Casting.
For ex:-
int s;
char i= '2';
s = (int) i;

Related

C# Formatting integers

I have an integer which I want to convert to a string, but taking the last 3 numbers and showing only the first 2 of them as decimals,
something like this: 85893 => 85.89
or failing that: 469 => 0.46
I have thought about rounding it, formatting it with string, even regex, but I would like to know what is the most optimal way to do it, since it will be done in several iterations per second
[UPDATE]
The best performing option I found was: #juharr
(num / 1000M).ToString("F2");
thanks a lot
It would appear your are truncating towards zero rather than rounding to get to 1/100ths.
I might do something like this:
public static string FormatSpecial( this int n )
{
return Math.Round( ((decimal) n) / 1000 , 2 , MidpointRounding.ToZero ).ToString();
}
If that is insufficiently efficient, perhaps something like this:
public static string FormatSpecial( this int n )
{
int ddd = n / 1000 ; // integer portion
int ttt = n % 1000 ; // fractional portion (1/1000ths)
int hh = thousands / 10 ; // truncate thousandths to 1/100ths
string s = string.Format("{0}.{1:00}", ddd, hh );
}
Just 3 integer divisions, followed by conversion to string.
I would hope that the optimizer and the JIT would collapse the 1st 2 divisions into a single machine instruction: on most CPUs, the integer division op usually produces both a quotient and remainder as its result.
If that's still insufficiently efficient, then something like this to optimize the string formatting. Since we know that the max value of a 64-bit unsigned integer (ulong) is 18446744073709551615, the resulting formatted string will never exceed 25 characters in length. So...
public static string FormatSpecial( this int n )
{
const BUFL = 25 ;
const DECIMAL_POINT = BUFL - 4 ;
const MIN = BUFL - 5 ;
char[] buf = new char[BUFL] ;
int i = BUFL - 1 ;
do
{
if ( i == DECIMAL_POINT)
{
buf[i--] = '.';
}
char digit = '0' + ( n % 10 );
buf[i--] = digit ;
n /= 10 ;
} while ( n != 0 || i > MIN );
int len = BUFL - i - 1;
return new String( buf , i , len );
}
If you care about precision, you could just take your numbers and multiply by 0.001, then take a Substring of it so that it chops off the last digit, I did it this way because it looks like you don't want it rounding depending on the last digit in the thousandths place of the decimal,
EDIT: After doing more research I found that if using newer versions of .Net you could use a System.ReadOnlySpan<T> since this is a reference to the string it won't create a new copy, so instead of the commented out line using .Substring() it would be like:
int num = 469;
string number = (num * 0.001).ToString("0.000");
//Console.WriteLine(number.Substring(0, number.Length - 1));
Console.WriteLine(number.AsSpan(0, number.Length - 1));
reference - (String.Substring() seems to bottleneck this code):
If you don't care about precision:
int num = 469;
Console.WriteLine(Math.Round(num * 0.001, 2));

C# Cannot convert `char' expression to type `string' [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have this code:
public class Kata
{
public static bool Narcissistic(int value)
{
//add variale to hold final result
int finalResult = 0;
//get the length of the value input
int valLength = value.ToString().Length;
//convert value given into an array of ints
string valString = value.ToString();
//iterate over each number and multiply that number by the length of value input
for (int i=0; i < valLength; i++) {
//convert char at index[i] of stringified value to int and mutiply by # of digits, store to result
finalResult += int.Parse(valString[i]) * valLength;
}
//return the result
return finalResult == value;
}
}
I'm getting an error when I run this that I understand, but don't quite know how to fix. My goal is to take a number (i.e 1234) and multiply each number by the total number of digits it contains (i.e 1*4 + 2*4 + 3*4...etc).
Assuming you have just Latin digit characters 0 to 9, you could use (valString[i] - '0') instead of int.Parse(valString[i]).
valString[i] is a char, not a string (which int.Parse() would expect). And chars are automatically converted to their Unicode integer code in C#, and as thhe digits 0 to 9 have consecutive Unicode values, '0' - '0' would be the Unicode value of the character for the digit 0 minus itself, i. e. 0, and so on up to '9' - '0' being 9 more than 0, i. e. 9.
This code would not work if there could be non Latin digits or non digit characters in your string. And looking at your complete code, the assumption should be met, as actually, you are converting from an int.
Here's a better option that avoids strings altogether
public static bool Narcissistic(int value)
{
if(value < 0) return false;
int sum = 0;
int count = 0;
while(value>0)
{
sum += value%10;
value /= 10;
count++;
}
return value == (sum*count);
}
Basically the value%10 will give you the least significate digit. Then the value /= 10; will truncate that digit. Once value is zero you've seen all the digits. And your formula (4*1 + 4*2 + 4*3 + 4*4) can of course just be 4*(1+2+3+4), which is the sum of the digits times the number of digits.
And presumably no negative number would be "Narcissistic" so you can just return false for them.
valString[i] will be a char - because that's what indexing does to a string. int.Parse expects a string. The simplest thing to do would probably just
finalResult += int.Parse(valString[i].ToString()) * valLength;
Assuming to turn a single character digit into a one-digit integer is your intention.
This is less "dangerous" than the traditional hack of subtracting '0' because you can rely on int.Parse to throw an exception if the char is anything but numeric.
You will also need to make the input argument uint, or define a behavior for negative numbers.
int.Parse() expects a string, but valString[i] is a character. You could just change this to valString[i].ToString(), but rather than parsing you can take advantage of the fact that the digit characters are encoded in sequence by casting them to int and subtracting the value of the 0 integer:
public static bool Narcissistic(int value)
{
int zero = (int)'0';
string valueString = value.ToString();
int total = 0;
foreach(char c in valueString)
{
int digit = ((int)c - zero);
total += digit * valueString.Length;
}
return total == value;
}
or
public static bool Narcissistic(int value)
{
int zero = (int)'0';
string valueString = value.ToString();
return valueString.Select(c => (c - zero) * valueString.Length).Sum() == value;
}
If you really want to you can write the second option as a one-liner:
public static bool Narcissistic(int value)
{
return value.ToString().Select(c => c - '0').Sum() * value.ToString().Length == value;
}

How to convert a certain string[index] to int in C#?

I have this code:
string number = "124235245423523423", number2 = "3423525232332325423";
for(i=number.length-1;i>=0;i--){
int save = Convert.ToInt32(number[i]) + Convert.ToInt32(number2[i]);
}
That is not the complete code but my question is why can't I convert and access some value at a certain index of a string as an integer? Isn't there a straight forward approach to this? I have tried some things but it didn't work out.
You're looking for int.Parse.
int save = int.Parse(number[3].ToString());
Converting a char to Int32 returns the value of that character in the current encoding.
For more information, see the MSDN documentation for Int32.Parse.
I think that this is what you are looking for. You have to access the string by the indexer value and then convert:
int yourNumber = Convert.ToInt32(number[4].ToString());
This will give you value 3
Here is one way to do it:
string number = "124235245423523423", number2 = "3423525232332325423";
for(int i=number.Length-1;i>=0;i--){
int save = int.Parse(number[i].ToString()) + int.Parse(number2[i].ToString());
Console.WriteLine(save);
}
When Convert.ToInt32() gets a char, it returns the UTF-16 encoded code unit of the value argument (read on MSDN).
On the other hand, when it gets a string, it returns the number that string contains, or throws an exception if it's not a number.
I believe the String.ToCharArray is what you're looking for:
https://msdn.microsoft.com/en-us/library/2c7h58e5(v=vs.110).aspx
I needed a value at a certain index, here's how i did it and it works wonderfully for me:
int number = (int)char.GetNumericValue(number[index])
What I actually did is that i converted the character at the index i needed into a double first through GetNumericValue method and then i converted that double into an integer.
string number = "124235245423523423", number2 = "3423525232332325423";
for(int i=number.Length-1;i>=0;i--){
int sum = int.Parse(number[i].ToString()) + int.Parse(number2[i].ToString());
Console.WriteLine(sum);
working example
Well, since number[i] is of type char you can convert it into corresponding int either by (the most general case)
int result = (int) char.GetNumericValue(number[i]);
please notice, that char.GetNumericValue returns double, it's actual for, say, '⅜' character (3/8 corrsponds to 0.375); or if you work with ['0'..'9'] range only, all you have to do is to subtract '0':
int result = number[i] - '0';
So far your code can be implemented as
// Math.Min - number.Length and number2.Length have diffrent size
// - 1 - strings are zero-based [0..Length - 1]
for (i = Math.Min(number.Length, number2.Length) - 1; i >= 0; i--) {
int save = number[i] + number2[i] - 2 * '0';
...
}
probably you want to right align both strings:
number = "124235245423523423"
+
number2 = "3423525232332325423"
------------------------------
354... ...846
in this case you have to modify for loop:
for (int i = 0; i < Math.Max(number.Length, number2.Length); ++i) {
int sum =
(i < number.Length ? number[number.Length - i - 1] : '0') +
(i < number2.Length ? number2[number2.Length - i - 1] : '0') -
2 * '0';
...
}

Get Sign of a Number without Logical Statement in C#

I want to get the Sign of a Number without a Logical Statement. Already a predefined method is available Math.Sign(). But I need to Implement in my own style.
The Tried C# Code:
public int GetSign(int value)
{
int bitFlag = 1;
var m = Convert.ToString(value, 2);
int length = m.Length;
if (m[length - 1] == '1')
{
bitFlag = -1;
}
return bitFlag;
}
Condition:
If the Last bit is 1 then return -1
If the Last bit is 0 then return 1
Kindly assist me, how to remove the above IF Statement...
Interesting thing about bit shifting:
If you right shift the bits, the leading bit will be propagated to the right.
Example byte : 10000000
Example byte >> 1 : 11000000
Integers take 32 bits to represent. So what happens if we shift the bits by 31 places? The leading bit will always be propagated, meaning all positive numbers will become 0 and all negative numbers will become -1.
Therefore :
public static int signOfInt(int input)
{
return (input >> 31);
}
will return 0 for positive numbers and -1 for negative numbers.
I think this will do it
public int GetSign(int value)
{
return -(((value & 1) << 1) - 1);
}

Reversing a hash function

I have the following hash function, and I'm trying to get my way to reverse it, so that I can find the key from a hashed value.
uint Hash(string s)
{
uint result = 0;
for (int i = 0; i < s.Length; i++)
{
result = ((result << 5) + result) + s[i];
}
return result;
}
The code is in C# but I assume it is clear.
I am aware that for one hashed value, there can be more than one key, but my intent is not to find them all, just one that satisfies the hash function suffices.
EDIT :
The string that the function accepts is formed only from digits 0 to 9 and the chars '*' and '#' hence the Unhash function must respect this criteria too.
Any ideas? Thank you.
This should reverse the operations:
string Unhash(uint hash)
{
List<char> s = new List<char>();
while (hash != 0)
{
s.Add((char)(hash % 33));
hash /= 33;
}
s.Reverse();
return new string(s.ToArray());
}
This should return a string that gives the same hash as the original string, but it is very unlikely to be the exact same string.
Characters 0-9,*,# have ASCII values 48-57,42,35, or binary: 00110000 ... 00111001, 00101010, 00100011
First 5 bits of those values are different, and 6th bit is always 1. This means that you can deduce your last character in a loop by taking current hash:
uint lastChar = hash & 0x1F - ((hash >> 5) - 1) & 0x1F + 0x20;
(if this doesn't work, I don't know who wrote it)
Now roll back hash,
hash = (hash - lastChar) / 33;
and repeat the loop until hash becomes zero. I don't have C# on me, but I'm 70% confident that this should work with only minor changes.
Brute force should work if uint is 32 bits. Try at least 2^32 strings and one of them is likely to hash to the same value. Should only take a few minutes on a modern pc.
You have 12 possible characters, and 12^9 is about 2^32, so if you try 9 character strings you're likely to find your target hash. I'll do 10 character strings just to be safe.
(simple recursive implementation in C++, don't know C# that well)
#define NUM_VALID_CHARS 12
#define STRING_LENGTH 10
const char valid_chars[NUM_VALID_CHARS] = {'0', ..., '#' ,'*'};
void unhash(uint hash_value, char *string, int nchars) {
if (nchars == STRING_LENGTH) {
string[STRING_LENGTH] = 0;
if (Hash(string) == hash_value) { printf("%s\n", string); }
} else {
for (int i = 0; i < NUM_VALID_CHARS; i++) {
string[nchars] = valid_chars[i];
unhash(hash_value, string, nchars + 1);
}
}
}
Then call it with:
char string[STRING_LENGTH + 1];
unhash(hash_value, string, 0);
Hash functions are designed to be difficult or impossible to reverse, hence the name (visualize meat + potatoes being ground up)
I would start out by writing each step that result = ((result << 5) + result) + s[i]; does on a separate line. This will make solving a lot easier. Then all you have to do is the opposite of each line (in the opposite order too).

Categories

Resources