【问题标题】:Int to char conversion, wrong numberInt 到 char 的转换,错误的数字
【发布时间】:2017-02-19 06:05:52
【问题描述】:

我有以下代码:

int a=-12;
char b=(char) a;
System.out.println(b);
System.out.println(b+0);

它首先打印出一些空字符,然后打印出一个数字 65524。如果我将 a 更改为 16,则显示的数字变为 65520。如果 a-2,则数字是 65534。

如果数字是正数且足够小,它会从 Unicode 表中打印出字符,如果一切正常,则返回字符的数字(与 a 相同),如果不正确(如果 @ 987654327@ 太大)。

例如,对于a = 8451,它返回℃(摄氏度)字符和a 本身(8451),但如果a=84510 它返回一些奇怪的中文符号并且与a 不同的数字(18974)。如果 a 更大 a=845100 它返回空 sumbol 和 58668。

问题是,这些数字是从哪里来的?

我试图找到答案,但到目前为止并不幸运。

编辑由于 int 到 char 是一种缩小转换,请考虑与byte a 相同的问题。现在显然不可能出现太大的数字,但我想知道负数会发生什么 - 将 byte a = -x 转换为 char 会得到与 int a 相同的奇怪数字。

【问题讨论】:

标签: java unicode casting


【解决方案1】:

int 是一个有符号的数字,有 4 字节32 位。 -12 的补码表示是

11111111 11111111 11111111 11110011 .

char 是一个无符号数,具有 2 字节16 位

int a=-12;
char b=(char)a;

二进制补码表示 b 是

11111111 11110011

相当于65524

【讨论】:

  • 第一个二进制数不是“-12的二进制补码”,它是(+)12的二进制补码,第二个二进制数相同,它不是:“b 的补码”,它只是 b(减少到 2 个字节) - 它是 (+)12 的二进制补码
  • @CarlosHeuberger 正数的二进制补码从 0 开始,负数从 1 开始。
  • 谢谢。你能告诉我,如果这个 char 数字在转换为 int 之后会发生什么?它看起来也像一个加宽转换,所以最左边的位应该用数字的最左边的位 (1) 填充,因此在 int 中我们得到-12,但它没有发生,它用零填充。
  • @fengsmith 你在混淆表示和运算:例如-12的补码表示是12的补码。定义:一个数的补码是等价的取该数的补码并加一;一个数的反码是通过反转它的所有位来获得的。因此,假设 0011(+3,假设只有 4 位)的二进制补码将是 1100 + 1 = 1101
  • @parsecer 是的,它用零填充,包括最左边的位。
【解决方案2】:

我认为这是因为 Java 中的char 是一个无符号的“双字节”整数。当 Byte 为 8 位时,双字节为 16 位 = 2 的 16 次方 = 65536 你得到 二的补码 (二进制减法运算)。

因为数字是无符号的,所有 16 位都用于表示整数,所以当你给出一个负数时,它会创建一个 溢出,你得到的数字是 (65536 + a),例如:

int a = -16; 你得到65536 - 16 = 65520(二进制:1111 1111 1111 0000)

int a = -2; 你得到65536 - 2 = 65534(二进制:1111 1111 1111 1110)

int a = 84510; 超过 char 的 65536 限制时,剩下 18974 (84510 - 65536 = 18974)。

你从 Unicode 表中得到一个字符,我猜是因为它是你定义的 字符集代码页

当你cast时你应该注意你转换的数据类型的值的范围,在这种情况下,intchar之间的区别。

【讨论】:

  • “机器”是 Java。您的第三段与随后的计算相矛盾。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多