zoukankan      html  css  js  c++  java
  • Java整数运算

    Java的整数运算遵循四则运算规则,可以使用任意嵌套的小括号。四则运算规则和初等数学一致。例如:

    // 四则运算

    public class Main {
    public static void main(String[] args) {
    int i = (100 + 200) * (99 - 88); // 3300
    int n = 7 * (5 + (i - 9)); // 23072
    System.out.println(i);
    System.out.println(n);
    }
    }

    整数的数值表示不但是精确的,而且整数运算永远是精确的,即使是除法也是精确的,因为两个整数相除只能得到结果的整数部分:

    int x = 12345 / 67; // 184
    

    求余运算使用%

    int y = 12345 % 67; // 12345÷67的余数是17
    

    特别注意:整数的除法对于除数为0时运行时将报错,但编译不会报错。

    溢出

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

    // 运算溢出

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

    要解释上述结果,我们把整数214748364015换成二进制做加法:

      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,因此,加法结果变成了一个负数。

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

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

    还有一种简写的运算符,即+=-=*=/=,它们的使用方法如下:

    n += 100; // 3409, 相当于 n = n + 100;
    n -= 100; // 3309, 相当于 n = n - 100;
    

    自增/自减

    Java还提供了++运算和--运算,它们可以对一个整数进行加1和减1的操作:

    移位运算

    在计算机中,整数总是以二进制的形式表示。例如,int类型的整数7使用4字节表示的二进制如下:

    00000000 0000000 0000000 00000111
    

    可以对整数进行移位运算。对整数7左移1位将得到整数14,左移两位将得到整数28

    int n = 7;       // 00000000 00000000 00000000 00000111 = 7
    int a = n << 1;  // 00000000 00000000 00000000 00001110 = 14
    int b = n << 2;  // 00000000 00000000 00000000 00011100 = 28
    int c = n << 28; // 01110000 00000000 00000000 00000000 = 1879048192
    int d = n << 29; // 11100000 00000000 00000000 00000000 = -536870912
    

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

    类似的,对整数28进行右移,结果如下:

    int n = 7;       // 00000000 00000000 00000000 00000111 = 7
    int a = n >> 1;  // 00000000 00000000 00000000 00000011 = 3
    int b = n >> 2;  // 00000000 00000000 00000000 00000001 = 1
    int c = n >> 3;  // 00000000 00000000 00000000 00000000 = 0
    

    如果对一个负数进行右移,最高位的1不动,结果仍然是一个负数:

    int n = -536870912;
    int a = n >> 1;  // 11110000 00000000 00000000 00000000 = -268435456
    int b = n >> 2;  // 11111000 00000000 00000000 00000000 = -134217728
    int c = n >> 28; // 11111111 11111111 11111111 11111110 = -2
    int d = n >> 29; // 11111111 11111111 11111111 11111111 = -1
    

    还有一种不带符号的右移运算,使用>>>,它的特点是符号位跟着动,因此,对一个负数进行>>>右移,它会变成正数,原因是最高位的1变成了0

    int n = -536870912;
    int a = n >>> 1;  // 01110000 00000000 00000000 00000000 = 1879048192
    int b = n >>> 2;  // 00111000 00000000 00000000 00000000 = 939524096
    int c = n >>> 29; // 00000000 00000000 00000000 00000111 = 7
    int d = n >>> 31; // 00000000 00000000 00000000 00000001 = 1
    

    byteshort类型进行移位时,会首先转换为int再进行位移。

    仔细观察可发现,左移实际上就是不断地×2,右移实际上就是不断地÷2。

    位运算

    位运算是按位进行与、或、非和异或的运算。

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

    n = 0 & 0; // 0
    n = 0 & 1; // 0
    n = 1 & 0; // 0
    n = 1 & 1; // 1
    

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

    n = 0 | 0; // 0
    n = 0 | 1; // 1
    n = 1 | 0; // 1
    n = 1 | 1; // 1
    

    非运算的规则是,01互换:

    n = ~0; // 1
    n = ~1; // 0
    

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

    n = 0 ^ 0; // 0
    n = 0 ^ 1; // 1
    n = 1 ^ 0; // 1
    n = 1 ^ 1; // 0
    

    对两个整数进行位运算,实际上就是按位对齐,然后依次对每一位进行运算。

    例如:

    // 位运算

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

    上述按位与运算实际上可以看作两个整数表示的IP地址10.0.17.7710.0.17.0,通过与运算,可以快速判断一个IP是否在给定的网段内。

    运算优先级

    在Java的计算表达式中,运算优先级从高到低依次是:

    • ()
    • ! ~ ++ --
    • * / %
    • + -
    • << >> >>>
    • &
    • |
    • += -= *= /=

    记不住也没关系,只需要加括号就可以保证运算的优先级正确。

    类型自动提升与强制转型

    在运算过程中,如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。例如,shortint计算,结果总是int,原因是short首先自动被转型为int

    // 类型自动提升与强制转型

    public class Main {
    public static void main(String[] args) {
    short s = 1234;
    int i = 123456;
    int x = s + i; // s自动转型为int
    short y = s + i; // 编译错误!
    }
    }

    也可以将结果强制转型,即将大范围的整数转型为小范围的整数。强制转型使用(类型),例如,将int强制转型为short

    int i = 12345;
    short s = (short) i; // 12345
    

    要注意,超出范围的强制转型会得到错误的结果,原因是转型时,int的两个高位字节直接被扔掉,仅保留了低位的两个字节:

    // 强制转型

    public class Main {
    public static void main(String[] args) {
    int i1 = 1234567;
    short s1 = (short) i1; // -10617
    System.out.println(s1);
    int i2 = 12345678;
    short s2 = (short) i2; // 24910
    System.out.println(s2);
    }
    }

    强制转型的结果很可能是错的。

  • 相关阅读:
    [五]SpringMvc学习-Restful风格实现
    [四]SpringMvc学习-对servlet与json的支持与实现
    [三]SpringMvc学习-封装、乱码问题、重定向、转发
    Android-aidl, binder,surfaceview
    linux memory dump--http://www.forensicswiki.org/wiki/Tools:Memory_Imaging
    Vanish/squid
    dongle --NFC
    词频统计 in office
    各种小巧的Hello World
    程序入口函数和glibc及C++全局构造和析构
  • 原文地址:https://www.cnblogs.com/flynn0825/p/12617912.html
Copyright © 2011-2022 走看看