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