227

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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
KeithA
  • 2,525
  • 3
  • 18
  • 15

20 Answers20

256

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.

phoenix
  • 7,988
  • 6
  • 39
  • 45
Paige Ruten
  • 172,675
  • 36
  • 177
  • 197
  • 7
    It assumes a certain character set. – EricSchaefer Oct 27 '08 at 08:32
  • 13
    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. – Paige Ruten Oct 27 '08 at 14:29
  • 3
    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. – Matthew Flaschen Apr 26 '09 at 03:39
  • 12
    @EricSchaefer But that's a safe assumption in C#: `char` is always UTF-16. – svick May 14 '14 at 15:48
  • 1
    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. – Sean Colombo Jun 04 '15 at 00:19
  • 5
    @svick 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. – Joel Coehoorn Dec 12 '18 at 19:49
  • 2
    @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](https://github.com/dotnet/corefx/issues/30503), but even that won't change `char`. – svick Dec 12 '18 at 22:22
  • 2
    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. – Nicholas Petersen Mar 02 '19 at 00:43
  • 1
    For F#, you must add explicit cast: `int foo - int '0'` – dudeNumber4 Feb 19 '20 at 16:04
  • 2
    `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. – AaronHolland Jun 09 '20 at 03:03
  • 1
    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. – Javid Feb 18 '21 at 18:11
216

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

Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
Chad Grant
  • 44,326
  • 9
  • 65
  • 80
  • 2
    ahh! so there is something native! Odd that it returns a double. I like this answer better. Thanks for pointing it out. – KeithA Apr 28 '09 at 14:35
  • 127
    @KeithA: There's a reason for it to return double: `char.GetNumericValue('¼')` yields 0.25. The joys of Unicode... ;-) – Heinzi Jun 26 '12 at 10:09
  • 4
    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 answer – Rusty Nail Jan 26 '17 at 08:20
  • 6
    @RustyNail in the case of the original question - asking specifically where he knows the char represents a number - *this* is the right answer – Don Cheadle Feb 16 '18 at 19:45
  • 1
    @mmcrae I don't think so - the original question asks for `char` to `int` without using `string` first. – NetMage Mar 25 '19 at 20:31
  • 1
    `if (char.IsDigit(character) == true) { return char.GetNumericValue(character); }` – JohnB Dec 17 '19 at 20:26
  • 1
    This answer would be more useful if it showed code examples. – SendETHToThisAddress Sep 30 '20 at 17:29
  • 1
    `int n = (int) Char.GetNumericValue('2')` Should do the trick! GetNumericValue returns a double, just need to cast it to an int. – Tigertron Jul 14 '21 at 11:13
108

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

faulty
  • 8,117
  • 12
  • 44
  • 61
  • 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. – Jay Bazuzi Oct 27 '08 at 05:41
  • 1
    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). – logout Aug 19 '10 at 11:55
  • 7
    @logout 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. – Roman Starkov Sep 22 '14 at 01:32
  • 1
    @RomanStarkov It is much easier to read! Why should there not be a parse method that hides this magical subtraction of characters from us? – sigma Sep 15 '22 at 07:45
  • @sigma 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. – Roman Starkov Sep 15 '22 at 09:22
31
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');
}
MarredCheese
  • 17,541
  • 8
  • 92
  • 91
sontek
  • 12,111
  • 12
  • 49
  • 61
  • 2
    This is what I was looking for. You could maybe explain what you are doing with the minus zero part. – Xonatron May 31 '18 at 01:18
18

Try This

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

int b = x - '0'; //That is '9' - '0' = 57 - 48 = 9
RollerCosta
  • 5,020
  • 9
  • 53
  • 71
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.

Nikolay
  • 1,076
  • 1
  • 13
  • 11
8

This converts to an integer and handles unicode

CharUnicodeInfo.GetDecimalDigitValue('2')

You can read more here.

Dan Friedman
  • 4,941
  • 2
  • 41
  • 65
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;
}
martijnn2008
  • 3,552
  • 5
  • 30
  • 40
Tomer Wolberg
  • 1,256
  • 10
  • 22
  • 3
    While this code snippet may be the solution, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-‌​code-based-answers) 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. – yivi Dec 26 '17 at 09:25
7

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.

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();
Hamit YILDIRIM
  • 4,224
  • 1
  • 32
  • 35
3

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

var character = '1';
var integerValue = int.Parse(character.ToString());
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

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
antonio
  • 548
  • 8
  • 16
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
Slai
  • 22,144
  • 5
  • 45
  • 53
1

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
mfluehr
  • 2,832
  • 2
  • 23
  • 31
Ian M
  • 11
  • 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%

Титан
  • 41
  • 1
  • 9
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;
}
Amir
  • 57
  • 1
  • 9
0

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

char testChar = 'e';
int result = Uri.IsHexDigit(testChar) 
               ? Uri.FromHex(testChar)
               : -1;
ElVit
  • 81
  • 5
0

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;
}
Marcel
  • 231
  • 3
  • 6
-1

This worked for me:

int bar = int.Parse("" + foo);
  • 7
    How is that different from `int.Parse(foo.ToString())`, except for being less readable? – svick May 14 '14 at 15:51
-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;
gamerdev
  • 65
  • 6