Java基本数据类型及其运算
1. 整型运算
-
四则运算
对于整型类型,Java只定义了带符号的整型,因此,最高位的bit表示符号位(0表示正数,1表示负数)。各种整型能表示的最大范围如下:
-
byte:-128 ~ 127
-
short: -32768 ~ 32767
-
int: -2147483648 ~ 2147483647
-
long: -9223372036854775808 ~ 9223372036854775807
因此存在溢出情况,求解溢出情况只需要将具体的数换为二进制进行加减即可,如果最高位变为1,则溢出之后的数又会变为负数
注:没有必要为了节省内存而使用byte和short进行整数运算,范围太小,即使确定了在byte类型内,后期的各种与int的转换会使代码十分冗余,难以维护
int i = 0 while(i>0){//不是死循环,因为会溢出变为负数 i += 1000; }
-
移位运算
在计算机种整数总是以2进制的形式存在
//左移,包括符号位向左截断相应的位数,而右边用0补上 int shitNum = 15;//00000000 00000000 00000000 00001111 int shitNumLeft1 = shitNum << 1;//00000000 00000000 00000000 00011110 System.out.println(shitNumLeft1);//移位之后在转换二进制的时候相当于多乘了一个2, 30 int shitNumLeft2 = shitNum << 2;//00000000 00000000 00000000 00111110 System.out.println(shitNumLeft2);//移位之后在转换二进制的时候相当于多乘了两个个2, 60 int shitNumLeft28 = shitNum << 28;//11110000 00000000 00000000 00000000 System.out.println(shitNumLeft28);//移位过多可能会造成负数 -268435456,也就是说左移运算用作乘2工具是有风险的 //左移一个负数,带符号移位,可能会变正,但也是乘2 shitNum = -15; int shitNumNevigateLeft = shitNum << 1; System.out.println(shitNumNevigateLeft);
左移相当于乘2,符号位在截断范围内,可能会出现正负交替的情况,如果没有发生有效数位的丢失那么左移几位就相当于乘以几次2,如果移动的位数大于32则先对32求余在移位余数(移33和移1一致),并且移位之后并没有改变原来的数,只是得到一个新数。注:观看以上看出左移是无法用作乘2工具的
//正数右移就是除2,最后会为0,移出的截断,右边0补充 int shitNum = 15;//00000000 00000000 00000000 00001111 int shitNumRight1 = shitNum >> 1;//00000000 00000000 00000000 0000111 System.out.println(shitNumRight1);//移位之后在转换二进制的时候相当于除一个2,7 int shitNumRight2 = shitNum >> 2;//00000000 00000000 00000000 00000011 System.out.println(shitNumRight2);//移位之后在转换二进制的时候相当于除两个个2, 3 int shitNumRight28 = shitNum >> 28;//00000000 00000000 00000000 00000000 System.out.println(shitNumRight28);//移位过多可能会造成0 //负数右移也是除2,但是最高位不动,最后为-1,就是 >> 对于负数来说为不带符号位的右移 int n = -536870912; int a = n >> 1; // 11110000 0000000 0000000 00000000 <= -268435456 int b = n >> 2; // 10111000 0000000 0000000 00000000 <= -134217728 int c = n >> 28; // 10000000 0000000 0000000 00000001 <= -2 int d = n >> 29; // 10000000 0000000 0000000 00000000 <= -1 //>>> 为带符号位的右移,负数一旦带符号移位就变为正数,但本质绝对值可能不再是除2 int n2 = -536870912; int a2 = n >>> 1; // 01110000 0000000 0000000 00000000 <= 1879048192 int b2 = n >>> 2; // 00111000 0000000 0000000 00000000 <= 939524096 int c2 = n >>> 29; // 00000000 0000000 0000000 00000111 <= 7 int d2 = n >>> 31; // 00000000 0000000 0000000 00000001 <= 1
右移相当于除2,>> 符号位不再移动范围内,>>>符号位在移动范围内,移动位数过多可能会为0,**并且右移运算符种的>>一定可以用作除法的工具,而且效率高。**如果移动的位数大于32则先对32求余在移位余数(移33和移1一致),并且移位之后并没有改变原来的数,只是得到一个新数。
-
位运算
- 与运算,两bit同为1为1
- 或运算,任意一bit为1为1
- 非运算,01互换
- 异或运算,两bit不同为1,相同为0
int i = 167776589; // 00001010 00000000 00010001 01001101 int n = 167776512; // 00001010 00000000 00010001 00000000 System.out.println(i & n); // 167776512
2.浮点数运算
浮点数运算与整数运算相比只能进行四则数值运算,不能移位运算,位运算,浮点数的表示范围比整形还要大,但是在计算机内部浮点数无法精确的表示。也就是说浮点数的运算存在误差,因此判断两个浮点数是否相等一般采用差值小于某个一个很小的数
// 比较x和y是否相等,先计算其差的绝对值:
double r = Math.abs(x - y);
// 再判断绝对值是否足够小:
if (r < 0.00001) {
// 可以认为相等
} else {
// 可以认为不相等
}
注:整数除0时会报错,浮点数除0时返回特殊值
double d1 = 0.0 / 0; // NaN
double d2 = 1.0 / 0; // Infinity
double d3 = -1.0 / 0; // -Infinity
3.布尔运算
boolean永远只有true和false两种值
短路运算 && || ,值得一提的是三元运算符也是短路运算符,确定结果之后不会执行剩下的表达式
4. 字符字符串
在Java种字符和字符串是两种不同的类型
4.1char
基本数据类型,一个char保存一个Unicode字符,可以直接将字符赋给char变量,也可以转义字符\u+Unicode编码值赋值,将字符赋给int类型就可以看到对应的Unicode编码。
char c = 'a';
char c = '\u0041';
int unicodeVlaue = 'a';
4.2String
引用类型变量,String具有不可变性,因为源码中用final 修饰了char[] ,因此二次对同一string变量赋值,其实是创建了新的字符串对象将引用直接替换了,原来的String对象将被垃圾回收机制回收。
String = "123 ";//可以包含空格
String = " 123 \"";//String 种用""标识字符串的开始结束,如果字符串本身包含",就用\",也有其他的转义字符
String message = "输出:";
int num = 9;
System.out.println(message + num);//+ 为字符串拼接,可以在多个字符串之间执行,也可以用字符串与其他任何类型进行拼接,形成新的字符串
引用类型变量的值可以为null值