Convert char to int in C#
Asked Answered
G

20

239

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.

Gennie answered 27/10, 2008 at 4:49 Comment(0)
P
222

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

Petrifaction answered 28/4, 2009 at 2:20 Comment(8)
ahh! so there is something native! Odd that it returns a double. I like this answer better. Thanks for pointing it out.Gennie
@KeithA: There's a reason for it to return double: char.GetNumericValue('¼') yields 0.25. The joys of Unicode... ;-)Oppen
This is not an answer that answers the actual question, Char.GetNumericValue('o'), Char.GetNumericValue('w') and any non numerical char will always return -1 - Jeremy Ruten has posted the correct answerTerris
@RustyNail in the case of the original question - asking specifically where he knows the char represents a number - this is the right answerMenken
@mmcrae I don't think so - the original question asks for char to int without using string first.Burlington
if (char.IsDigit(character) == true) { return char.GetNumericValue(character); }Valadez
This answer would be more useful if it showed code examples.Dyscrasia
int n = (int) Char.GetNumericValue('2') Should do the trick! GetNumericValue returns a double, just need to cast it to an int.Frankenstein
L
277

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.

Latinalatinate answered 27/10, 2008 at 4:51 Comment(11)
It assumes a certain character set.Bomar
No it doesn't, as long as the digits are in order (which compilers require of the charset) it will work, no matter what value they start on.Latinalatinate
This is fine, except that you still need to do bounds-checking first, and at that point I'm not sure whether int.parse(foo.ToString()) is faster.Harem
@Bomar But that's a safe assumption in C#: char is always UTF-16.Gruelling
This works for letters too... so you could do: char foo = 'b'; int bar = foo - 'a'; // now you can see that 'bar' is the 2nd letter (index 1) in the alphabet.Barge
@Gruelling small point and old now, but in the time since you posted this we've had Core come out, which uses UTF-8. Still a safe assumption, though.Kaleb
@JoelCoehoorn That's not true, char in .Net Core is still UTF-16. There is work being done to add UTF-8 string in a future version of .Net Core, but even that won't change char.Gruelling
Just wow ... most impressive. And I've been working with char sets all day long with heavy conversions to int / uint decimal (i.e. numeric) values, greater than / lesser than comparisions, etc, but never thought of this simple but brilliant way.Pretty
For F#, you must add explicit cast: int foo - int '0'Underact
char foo = 'a'; int bar = foo - '0'; -> bar == 49, which is probably not what you want. You'd want to check that 0 <= bar <= 9 afterwards.Milt
Warning: This is a non-standard solution. It doesn't work with localized digits (like arabic digits). That's why it really works only for ASCII.Conga
P
222

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

Petrifaction answered 28/4, 2009 at 2:20 Comment(8)
ahh! so there is something native! Odd that it returns a double. I like this answer better. Thanks for pointing it out.Gennie
@KeithA: There's a reason for it to return double: char.GetNumericValue('¼') yields 0.25. The joys of Unicode... ;-)Oppen
This is not an answer that answers the actual question, Char.GetNumericValue('o'), Char.GetNumericValue('w') and any non numerical char will always return -1 - Jeremy Ruten has posted the correct answerTerris
@RustyNail in the case of the original question - asking specifically where he knows the char represents a number - this is the right answerMenken
@mmcrae I don't think so - the original question asks for char to int without using string first.Burlington
if (char.IsDigit(character) == true) { return char.GetNumericValue(character); }Valadez
This answer would be more useful if it showed code examples.Dyscrasia
int n = (int) Char.GetNumericValue('2') Should do the trick! GetNumericValue returns a double, just need to cast it to an int.Frankenstein
D
115

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

Dilatometer answered 27/10, 2008 at 5:39 Comment(5)
Absolutely the right approach. Choose the first one if you want non-int inputs to throw, the second if you want to do something else.Broomrape
This is a good approach for a generic conversion method. As an aside, its another example of how .NET promotes bloatware. (I mean go on and unit-test TryParse() and ToString() - you can't, not practically).Prelate
@Prelate no, it's an example of how an answer on StackOverflow promotes bloatware. This is indeed unnecessarily bloated, and I don't understand why this is considered superior to subtracting '0' from the char.Kindness
@RomanStarkov It is much easier to read! Why should there not be a parse method that hides this magical subtraction of characters from us?Thermostat
@Thermostat that's true, if this subtraction is magical then it's understandable that you want it hidden. But you're hiding just a single subtraction!!! To me it's a bit like a DivideApplesBetweenPeople(people: 3, apples: 15) that hides all the "magical math" from you, even though this math is trivial.Kindness
A
33
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');
}
Alkalize answered 27/10, 2008 at 4:52 Comment(1)
This is what I was looking for. You could maybe explain what you are doing with the minus zero part.Weasel
R
18

Try This

char x = '9'; // '9' = ASCII 57

int b = x - '0'; //That is '9' - '0' = 57 - 48 = 9
Riggle answered 30/12, 2011 at 7:3 Comment(1)
Your comment says '9', but your code has 9, which won't compile.Gruelling
C
10

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.

Congregationalist answered 26/10, 2012 at 6:59 Comment(0)
C
9

This converts to an integer and handles unicode

CharUnicodeInfo.GetDecimalDigitValue('2')

You can read more here.

Carrolcarroll answered 18/4, 2015 at 2:32 Comment(0)
R
8

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.

Radioactive answered 12/4, 2018 at 18:8 Comment(0)
I
7

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;
}
Intuit answered 26/12, 2017 at 8:36 Comment(1)
While this code snippet may be the solution, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.Kilk
T
6

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();
Thermometer answered 17/6, 2019 at 15:4 Comment(0)
G
4

First convert the character to a string and then convert to integer.

var character = '1';
var integerValue = int.Parse(character.ToString());
Granular answered 9/6, 2021 at 17:10 Comment(0)
H
3

One very quick, simple way is to just convert chars 0-9 to integers: C# treats a char value much like an integer.

char c = '7'; // ASCII code 55
int i = c - 48; // integer of 7
Hallerson answered 10/8, 2021 at 19:41 Comment(0)
S
2

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

Scandura answered 13/8, 2015 at 6:42 Comment(0)
B
2

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
Brutify answered 14/1, 2017 at 21:54 Comment(0)
E
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%

Ezaria answered 16/5, 2022 at 2:49 Comment(0)
I
0

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;
}
Izard answered 13/6, 2021 at 6:16 Comment(0)
P
-1

This worked for me:

int bar = int.Parse("" + foo);
Pollerd answered 26/8, 2013 at 2:7 Comment(1)
How is that different from int.Parse(foo.ToString()), except for being less readable?Gruelling
G
-1

Use Uri.FromHex.
And to avoid exceptions Uri.IsHexDigit.

char testChar = 'e';
int result = Uri.IsHexDigit(testChar) 
               ? Uri.FromHex(testChar)
               : -1;
Gnu answered 7/9, 2021 at 13:49 Comment(0)
S
-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;
}
Shute answered 5/1, 2023 at 8:19 Comment(0)
I
-5

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;
Imogene answered 29/5, 2017 at 18:22 Comment(4)
This would return the ASCII code of the character 2, not the value 2.Unisexual
Then how about using char.GetNumericValue (It returns a double value) and casting it to int.Imogene
Yup, that's what @Chad Grant's accepted answer proposesUnisexual
this was actually what I was searching for when I found this stackDerbyshire

© 2022 - 2024 — McMap. All rights reserved.