动手动脑
原码、反码、补码概念
原码:
原码是一种简单的机器数表示法。对于一个有符号数,最高位为符号位(0 表示正数,1 表示负数),其余位表示数值的绝对值。例如,在 8 位二进制数中,+5 的原码是 00000101, -5 的原码是 10000101。
反码:
对于正数,反码与原码相同。对于负数,反码是在原码的基础上,符号位不变,其余位按位取反。例如, -5 的原码是 10000101,其反码是 11111010。
补码:
对于正数,补码与原码相同。对于负数,补码是其反码加 1。例如, -5 的原码是 10000101,反码是 11111010,补码是 11111011。
点击查看代码
public class bianma {
public static void main(String[] args) {
// 测试正数
int positive = 5;
// 原码
String positiveOriginalCode = Integer.toBinaryString(positive);
System.out.println("正数5的原码(以8位为例): " + addLeadingZeros(positiveOriginalCode, 8));
// 反码
System.out.println("正数5的反码(与原码相同): " + addLeadingZeros(positiveOriginalCode, 8));
// 补码
System.out.println("正数5的补码(与原码相同): " + addLeadingZeros(positiveOriginalCode, 8));
// 测试负数
int negative = -5;
// 原码
String negativeOriginalCode = Integer.toBinaryString(negative);
System.out.println("负数 - 5的原码(以8位为例): " + addLeadingZeros(negativeOriginalCode, 8));
// 求反码
String negativeOneComplement = Integer.toBinaryString(~negative);
System.out.println("负数 - 5的反码(以8位为例): " + addLeadingZeros(negativeOneComplement, 8));
// 求补码
int negativeTwoComplement = -negative;
String negativeTwoComplementBinary = Integer.toBinaryString(negativeTwoComplement);
System.out.println("负数 - 5的补码(以8位为例): " + addLeadingZeros(negativeTwoComplementBinary, 8));
// 进行位操作并对比
// 例如,对正数进行按位与操作
int positiveAndResult = positive & 3;
System.out.println("正数5与3按位与的结果: " + positiveAndResult);
// 手工计算正数5(00000101)与3(00000011)按位与为1(00000001),结果一致
// 对负数进行按位或操作
int negativeOrResult = negative | 3;
System.out.println("负数 - 5与3按位或的结果: " + negativeOrResult);
// 手工计算 - 5(11111011)与3(00000011)按位或为 - 5(11111011),结果一致
}
public static String addLeadingZeros(String binaryString, int totalLength) {
while (binaryString.length() < totalLength) {
binaryString = "0" + binaryString;
}
return binaryString;
}
}
在 Java 中,整数类型(如int)采用补码表示。这是因为补码在计算机运算中有很多优点,例如可以简化加减法运算电路等。通过上述示例程序中的位操作结果与手工计算结果对比,也可以发现 Java 中的数在进行位操作时符合补码的运算规则。
同名变量的屏蔽原则
在 Java 中,同名变量的屏蔽原则(也称为变量隐藏或变量遮蔽)是指当在一个内部作用域(如方法内部、代码块内部等)中定义了一个与外部作用域同名的变量时,在内部作用域中,这个同名变量会屏蔽外部作用域中的变量。这意味着在内部作用域中访问该变量名时,访问的是内部定义的这个变量,而不是外部作用域中的同名变量。当内部作用域结束后,外部作用域的同名变量又可以被正常访问(如果外部作用域仍然在有效范围内)。
点击查看代码
public class a {
public static void main(String[] args) {
int num = 10;
System.out.println("外部定义的num值: " + num);
{
num = 20;
System.out.println("内部代码块定义的num值: " + num);
}
System.out.println("再次访问外部定义的num值: " + num);
// 方法中的同名变量
anotherMethod();
}
public static void anotherMethod() {
int num = 30;
System.out.println("anotherMethod中定义的num值: " + num);
{
num = 40;
System.out.println("anotherMethod内部代码块定义的num值: " + num);
}
System.out.println("再次访问anotherMethod中定义的num值: " + num);
}
}
类型转换
byte:8bit
short:16bit
int:32bit
long:64bit
flot:32bit
double:64bit
char:16bit
double>float>long>int>short>byte
整数类型之间的转换:
小类型转换为大类型(如 byte 到 short、int、long):无精度损失。例如将byte类型的值赋给short类型变量时,因为大类型有更多的位数来表示数值,所以能够准确表示小类型的值。
大类型转换为小类型(如 long 到 int、short、byte):可能会有精度损失。当把一个较大范围的数据类型转换为较小范围的数据类型时,如果大类型的值超出了小类型的数值范围,就会发生数据截断,导致精度损失。
整数类型与浮点类型之间的转换:
整数转换为浮点类型(如 int 到 float、double):可能有精度损失。虽然浮点类型能够表示比整数类型更大的数值范围,但在表示一些整数时可能会有精度问题。
点击查看代码
int num = 1234567890;
float f = num;
// f的值可能与num不完全相等,因为float的有效数字有限
浮点类型转换为整数类型(如 float 到 int、double 到 int 等):会有精度损失。浮点类型包含小数部分,转换为整数类型时,小数部分会被截断。
浮点类型之间的转换:
float 到 double:无精度损失。因为double类型有更多的位数来表示数值,能够更精确地表示float类型的值。
double 到 float:可能有精度损失。因为float的有效数字和数值范围都小于double,当double类型的值超出float的有效数字范围或者数值范围时,就会出现精度损失。
使用double类型的数值进行计算, 其结果是不精确的
点击查看代码
public class TestDouble {
public static void main(String args[]) {
System.out.println("0.05 + 0.01 = " + (0.05 + 0.01));
System.out.println("1.0 - 0.42 = " + (1.0 - 0.42));
System.out.println("4.015 * 100 = " + (4.015 * 100));
System.out.println("123.3 / 100 = " + (123.3 / 100));
}
}
输出语句
点击查看代码
public class b {
public static void main(String[] args) {
int X=100;
int Y=200;
System.out.println("X+Y="+X+Y);//X+Y=100200
System.out.println("X+Y="+(X+Y));//X+Y=300
System.out.println(X+Y+"=X+Y");//300=X+Y
}
}