如何将字符转换为整数?

130

如何以正确的方式将 char 转换为 int? 这会返回 49

int val = Convert.ToInt32('1');
//int val = Int32.Parse("1"); // Works

我不想将其转换为字符串,然后再解析。

11个回答

298

我很惊讶没有人提到静态方法直接内置在 System.Char 中...

int val = (int)Char.GetNumericValue('8');
// val == 8

19
不错的发现!+1 虽然返回一个“double”很奇怪。 - Marc Gravell
4
我同意,我也搞不明白为什么会返回“double” - 一个单独的字符怎么可能表示浮点数呢? - Joel Mueller
51
有许多Unicode字符可以表示非整数,例如U+2153 - dtb
26
@dtb - 我之前没有考虑到这一点。Char.GetNumericValue('⅓')确实会返回0.3333...。感谢您指出这一点! - Joel Mueller
逆函数存在吗? - watbywbarif
1
注:此函数目前在NetMF中不可用。 - GisMofx

40

char c怎么样呢?

int i = (int)(c - '0');

哪种方法可以对字符值进行减法操作?

关于API的问题(评论),也许可以使用扩展方法?

public static class CharExtensions {
    public static int ParseInt32(this char value) {
        int i = (int)(value - '0');
        if (i < 0 || i > 9) throw new ArgumentOutOfRangeException("value");
        return i;
    }
}

然后使用 int x = c.ParseInt32();


1
我应该提到,我知道这个,但还有其他方法吗?我想知道是否有API可以做到这一点? - tvr
4
如果你想要类似于 int.Parse 的行为,即在无效输入时抛出异常,那么你需要添加额外的边界检查:if (i < 0 || i > 9) throw new FormatException(); - Dirk Vollmar
@user386338 - 已更新一个API选项,同时包含了@0xA3的反馈。 - Marc Gravell
那么,我应该使用哪个?(int)Char.GetNumericValue(ch); 还是 (int)(c - '0'); 还是 c & 0x0f(可能更快)? - Jack
@Jack,如果你想要更快的话,那就计时(使用大量迭代),你就会得到答案。 - Marc Gravell
显示剩余2条评论

21

大家都忽略了解释为什么会发生这种情况。

Char基本上是一个整数,但它指向ASCII表中的一个指针。所有字符都有相应的整数值,当您尝试解析它时,可以清楚地看到这一点。

Pranay显然有不同的字符集,这就是他的代码不起作用的原因。唯一的方法是

int val = '1' - '0';

因为这个过程在表格 '0' 中查找整数值,然后得到了“基准值”,从该值中减去以字符格式表示的数字即可得到原始数字。


16
int i = (int)char.GetNumericValue(c);

另一种选择:

int i = c & 0x0f;

这也应该可以实现。


4
int val = '1' - '0';

这可以使用ASCII码来完成,其中'0'是最低的数字字符,其余数字字符依次递增。


这很棒!在我看来,这是最优雅的解决方案。 - arabisoft

3
int val = '1' - 48;

@Luke Xu:'0' 的 ASCII 码为 0x30,十进制为48,所以与 '1' - '0' 相同。 - NiKiZe

3

You may use the following extension method:

public static class CharExtensions
    {
        public static int CharToInt(this char c)
        {
            if (c < '0' || c > '9')
                throw new ArgumentException("The character should be a number", "c");

            return c - '0';
        }
    }

1
@0xA3 一般来说,范围检查必须在方法的开头进行。从语义上讲,如果我们要将 char 转换为 int,我们必须检查输入参数的范围,而不是输出的 int 值的范围。 - Eugene Cheverda
不需要检查结果的 int 值,因为在方法开始时已经执行了数字字符范围检查,所以如果指定的字符不在数字字符范围内,将抛出异常并得到正确的结果值。与您提供的逻辑相同,但是在方法开始时执行了范围检查。 - Eugene Cheverda
抱歉,我误读了你的代码示例。有时候最明显的东西很难看到。我敢打赌代码应该是这样写的:if (c < 0 || c > 9)... - Dirk Vollmar

1
int val = '1' & 15;

ASCII字符0-9的二进制为:

0 - 00110000

1 - 00110001

2 - 00110010

3 - 00110011

4 - 00110100

5 - 00110101

6 - 00110110

7 - 00110111

8 - 00111000

9 - 00111001

如果你取每个数字的前4位LSB(使用与8'b00001111的按位AND运算,等于15),你就得到了实际的数字(0000 = 0,0001 = 1,0010 = 2,...)


从类型的角度来看,这是如何工作的?您正在使用char和int之间的按位运算符,然后返回一个int?逻辑AND是否使用char和int的二进制表示,并返回一个二进制表示,然后由于您将变量定义为int,因此它使用该表示? - mitomed
@mitnomed 是的,如果你使用 byte 作为例子,那么它会使用 byte 表示。 - Tomer Wolberg

1

TryParse 适用于字符串而不是字符。 - tvr
是的,但这仍然是实现转换的最安全方式。 - MUG4N
1
将单个字符转换为整数是一项安全问题吗? - Joel Mueller
1
在这种情况下,“安全”意味着如果您的字符实际上不是ASCII数字(可能是多字节Unicode字符),它不会引起问题。 - Robin Bennett

0

在其他答案的基础上进行扩展,涉及十六进制表示:

public int CharToInt(char c) 
{
    if (c >= '0' && c <= '9') 
    {
        return c - '0';
    }
    else if (c >= 'a' && c <= 'f') 
    {
        return 10 + c - 'a';
    }
    else if (c >= 'A' && c <= 'F') 
    {
        return 10 + c - 'A';
    }

    return -1;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接