我有以下代码:
static char toUpper(char c)
{
if (c >= 'a' && c <= 'z')
return (char) (c & ~('a' - 'A'));
return c;
}
为什么这可以正确输入大写字母?按位运算是我最感兴趣的。我或多或少地理解数学,我知道它确实有效,但不是它为什么有效的根本原因。
我有以下代码:
static char toUpper(char c)
{
if (c >= 'a' && c <= 'z')
return (char) (c & ~('a' - 'A'));
return c;
}
为什么这可以正确输入大写字母?按位运算是我最感兴趣的。我或多或少地理解数学,我知道它确实有效,但不是它为什么有效的根本原因。
它之所以有效,是因为在 ASCII(与 Unicode 的下半部分相同)中,位模式为A
( 0100 0001
)0x41
而a
为0110 0001
( 0x61
)。
因此'a' - 'A'
is 0x20
or 0010 0000
,这是您必须在小写字母上清除以使其大写的位。
您可以从下表中看到,大写的范围从0x41
through0x5a
和等效的小写字母从0x61
through 0x7a
:
清除位位置的方法是and
对该位置进行逻辑否定。
因此(使用 8 位)~0x20
是0xdf
( 1101 1111
) 并且字母的操作c
如下所示:
0110 0011 0x63 or 'c'
& 1101 1111 0xdf, or ~('a' - 'A')
---- ----
0100 0011 0x43 or 'C'
有关按位运算符的更详细介绍,请参见此处。
当然,值得一提的是,您可以更轻松地使用:
c = Character.toUpperCase (c);
无需编写自己的函数。有关详细信息,请参见此处。而且,如果您真的想将其限制为 ASCII 小写字母,您仍然可以将其包装在if
语句中,尽管如果您希望您的应用程序在非 ASCII 世界中使用,我建议这不是一个好主意。
让我们举个例子来理解你的代码。
1) 假设您将字符 'p' 传递给您的方法toUpper()。
2) 现在您的 if 语句中的条件将始终为真,因为任何字母都介于“a”和“z”之间。
3)在 if 语句中,您有以下代码
return (char) (c & ~('a' - 'A'));
4)在上述声明中这部分
('a' - 'A')
将始终首先执行,因为它在括号中。在这里,您只是从“a”中减去“A”,即 97-65,它们是 ASCII 值。(A---> 65 和 a----> 97)。因此,无论您传递给toUpper()方法的字符如何,答案总是 32 。
5) 那么怎么有操作符~即
~('a' - 'A')
正如我所说的 ('a' - 'A') 的答案总是 32,因此运算符 ~ 应用于数字 32 即
~32
预测算子~的输出,公式如下图
~(number)
= -(number) - 1
因为这里的数字是 32,所以上面公式的 ~32 的输出是
-(32) - 1
= -32 - 1
= -33
所以输出
~('a' - 'A')
总是-33
5)现在你有
(c & ~('a' - 'A'))
IE
(c & -33)
这里 c 有用户传递的字母表,在我们的例子中是 'p'
IE
p & -33
由于 'p' 的 ASCII 值是 112,即
112 & -33
IE
1110000 & 1011111
分别是二进制112和-33的对应值
所以在应用运算符 & 我们得到
1010000
6) 现在将 1010000 转换为十进制,我们得到 80,这是大写字母“P”的 ASCII 值。
7)所以一般来说我们可以说将要执行的操作是
(ASCII value of user inputted alphabet) & -33
8)还有一件事“Java适用于Unicode。但是Unicode中的第一组字符是ASCII,@paxdiablo也说过。所以我在上面的答案中提到了ASCII。
在 Java 中,字符只是无符号的 16 位整数。
对于 ascii,小写字符为 97-122,对应的大写字母为 65-90。所以你只需要从每个值中减去 32。
如果您查看代码(char) (c & ~('a' - 'A'))
,您可以从内而外地评估它开始。
'a' - 'A'
给你所需偏移量的负数,32。
~(32)
翻转位,所以你现在有 -33。这是一个位掩码,除了倒数第六位 1 之外的所有内容。
(c & -33)
应用位掩码,将适当的位设置为 0。这实际上减去了 32。
(char)
只是做一个不必要的转换回 char (编译器无论如何都会插入一个转换)。
字符表示为数字。请查看ascii 表以了解每个字符被映射到的数字。
上面的按位运算,基本就是把小写字母对应的数字变成了大写字母对应的数字