数值类型的运算方式总结

一:常见的位运算使用场景

1. 位运算

        位运算是按照整教的二进制位进行移位、与、或、非、异或的运算,应用于整数类型( int),长整型( long),短整型( short ),字符型( char ),和字节型( byte )等数据类型(浮点型不能进行位运算)。由于,位运算由于直接采用二进制进行计算,所以往往可以得到计算性能的提升。

        Java中的常见位运算有6种:

<<    左移
>>    右移
&     位与
|     位或
~     位非
^     位异或

1.1.移位运算 << >>

在计算机中,整数总是以二进制的形式表示。                                                                                   

例如:int类型的整数7使用4字节表示的二进制。

00000000 0000000 0000000 00000111

 对整数7进行左移,作用等同于n×2^位运算 ,结果如下:

int n = 7;       // 00000000 00000000 00000000 00000111 = 7
int a = n << 1;  // 00000000 00000000 00000000 00001110 = 14 相当于 7 乘 2的1次方
int b = n << 2;  // 00000000 00000000 00000000 00011100 = 28 相当于 7 乘 2的2次方
int c = n << 28; // 01110000 00000000 00000000 00000000 = 1879048192 相当于 7 乘 2的28次方
int d = n << 29; // 11100000 00000000 00000000 00000000 = -536870912 相当于 7 乘 2的29次方

 注意:
左移29位时,由于最高位变成1,因此结果变成了负数。

对整数28进行右移,作用等同于 n ÷ 2^位移数 ,结果如下:

int n = 28;      // 00000000 00000000 00000000 00011100 = 28
int a = n >> 1;  // 00000000 00000000 00000000 00001110 = 14 = 28 除 2的1次方
int b = n >> 2;  // 00000000 00000000 00000000 00000111 = 7 = 28 除 2的2次方
int c = n >> 3;  // 00000000 00000000 00000000 00000011 = 3 = 28 除 2的3次方

 简单来理解:左移实际上执行乘法,右移实际上执行除法

1.2.与运算 &

&与运算的规则是:必须两个数同时为1,结果才为1

public class Main {
    public static void main(String[] args) {
        int i = 167776589; // 00001010 00000000 00010001 01001101
        int n = 167776512; // 00001010 00000000 00010001 00000000
        int x = i & n;     // 00001010 00000000 00010001 00000000
        System.out.println(x); // 167776512
    }
}

1.3.或运算 |

|或运算的规则是:只要任意一个为1,结果就为1

public class Main {
    public static void main(String[] args) {
       int i = 167776589;  // 00001010 00000000 00010001 01001101
       int n = 167776512;  // 00001010 00000000 00010001 00000000
       int x = i | n;      // 00001010 00000000 00010001 01001101
       System.out.println(x); // 167776589
    }
}

1.4.非运算 ~

~非运算的规则是:0和1互换(反转)

public class Hello {
	public static void main(String[] args) {
		int i = 167776589;  // 00001010 00000000 00010001 01001101
	    int x = ~i;         // 11110101 11111111 11101110 10110010
	    System.out.println(x); // -167776590
	}
}

1.5.异或运算 ^

^异或运算的规则是:如果两个数不同,结果为1,否则为0。

public class Hello {
	public static void main(String[] args) {
		int i = 167776589; // 00001010 00000000 00010001 01001101
		int n = 167776512; // 00001010 00000000 00010001 00000000
		int x = i ^ n;     // 00000000 00000000 00000000 01001101
		System.out.println(x); // 77
	}
}

2.常见用途

●移位运算,计算指定数值n的50%:n >> 1
●移位运算,计算指定数值n的2倍:n << 1
●与运算,判断奇偶数
        ○a&1 == 0 偶数
        ○a&1 == 1 奇数
●求平均值,防止溢出
        ○(x&y)+((x^y)>>1)
●异或运算,交换两个整数

二:整数类型运算时的类型溢出问题,产生原因以及解决办法

1.溢出

由于整数存在范围限制,如果计算结果超出了范围,就会产生溢出,而溢出不会出错,会得到一个奇怪的结果。

例如:

public class Main {
    public static void main(String[] args) {
        int x = 2147483640;
        int y = 15;
        int sum = x + y;
        System.out.println(sum); // -2147483641
    }
}

 解释上述结果:把整数2147483640和15换成二进制做加法,观察一下运算过程。

  0111 1111 1111 1111 1111 1111 1111 1000
+ 0000 0000 0000 0000 0000 0000 0000 1111
-----------------------------------------
  1000 0000 0000 0000 0000 0000 0000 0111

 由于最高位计算结果为1,因此,加法结果变成了一个负数。

2.解决方法

解决上面的问题,可以把int换成long类型,由于long可表示的整型范围更大,所以结果就不会溢出:

long x = 2147483640;
long y = 15;
long sum = x + y;
System.out.println(sum); // 2147483655

注意:如果超出long范围可以使用BigInteger 

三:浮点类型运算时的精度丢失问题,产生原因以及解决办法

1.浮点数精度丢失

        浮点数运算和整数运算相比,只能进行加减乘除这些数值计算,不能做位运算和移位运算。在计算机中,浮点数虽然表示的范围大,但是,浮点数有个非常重要的特点,就是浮点数常常无法精确表示,会出现精度丢失问题。

例如:
        浮点数0.1在计算机中就无法精确表示,因为十进制的0.1换算成二进制是一个无限循环小数,很显然,无论使用float还是double,都只能存储一个0.1的近似值。但是,0.5这个浮点数又可以精确地表示。
        由于,浮点数常常无法精确表示,因此,浮点数运算也会产生误差。
例如:

public class Main {
    public static void main(String[] args) {
        double x = 10 - 9.9;
		double y = 1.0 - 9.0 / 10;
        
        // 观察x和y是否相等:
        System.out.println(x);
        System.out.println(y);
        
        // 判断x是否等于y
        System.out.println(x == y);
		System.out.println(Math.abs((x-y)) < 0.00001);
    }
}

2.解决方法

在java中可以使用BigDecimal

BigDecimal可以表示一个任意大小且精度完全准确的浮点数。

BigDecimal bd = new BigDecimal("123.4567");
System.out.println(bd.multiply(bd)); // 15241.55677489

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值