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);
    }
}

输出

3300
23072

整数运算的数值不但是精确的,而且整数运算永远是精确的,即使是出发,因为两个整数相除只得到结果的整数部分,不进行四舍五入

int x=11/3;

求余运算

int x=11%3;

整数除法对于被除数为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

要解释上述结果,我们把整数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,因此加法结果变成了一个负数

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

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

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

n+=100; //相当于n=n+100
n-=100;//相当于n=n-100

自增/自减

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

public class Main {
    public static void main(String[] args) {
        int n=100;
        n++;
        System.out.println(n);
        n--;
        System.out.println(n);
    }
}

注意++写在前面和后面计算结果是不同的,++n表示先加1再引用n,n++表示先引用n再加1。不建议把++运算混入到常规运算中,容易自己把自己搞懵了。

移位运算

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

00000000 00000000 00000000 00000111

可以对整数进行移位运算。对整数7左移1位将得到整数14,左移2位将得到整数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,因此结果变成了负数

类似地对证书7进行右移结果如下

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;  // 10111000 00000000 00000000 00000000 = -134217728
int c = n >> 28; // 11111111 11111111 11111111 11111110 = -2

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

对byte和short类型进行位移时,会首先转换为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

非运算的规则是,0和1呼唤

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;
        int n = 167776512;
        System.out.println(i&n);
    }
}

运行结果

167776512

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

运算优先级

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

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

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

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

在运算过程中,如果参与运算的两个数类型不一致,那么计算结果为较大类型的整型。例如,short和int计算,结果总是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);
    }
}

结果

-10617
24910

为什么结果是-10617和24910呢

首先把1234567转换成二进制并且使用8位分割成4份

00000000 00010010 11010110 10000111‬

强制转换成short类型或高位被抛弃留下低位两个字节

11010110 10000111

最高位为1是负数,负数是以补码的形式存储在计算机内需要转换成原码

原码等于补码-1后除符号位取反

补码-1结果

11010110 10000110

除符号位取反得到原码

10101001 01111001

最高位为1所以是负数101001 01111001即-10617

同理计算12345678去掉高两位后剩下的最高位为0是正数则补码和原码是一样的

练习

计算自然数之和

public class Main {
    public static void main(String[] args) {
        int n=100;
        int sum=0;
        for(int i=1;i<=n;i++) {
            sum=sum+i;
        }
        System.out.println(sum);
    }
}

小结

整数运算的结果永远都是精确的

运算结果会自动提升

可以强制转型,但超出范围的强制转型会得到错误的结果

应该选择合适范围的整型(int或long),没有必要为了节省内存而使用byte和short进行整数运算。

总结

到此这篇关于Java基础教程之整数运算的文章就介绍到这了,更多相关Java整数运算内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java正则验证正整数的方法分析【测试可用】

    本文实例讲述了Java正则验证正整数的方法.分享给大家供大家参考,具体如下: package des; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Num { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Num p=new Num(); S

  • Java判断字符串是否是整数或者浮点数的方法

    如下所示: //判断整数(int) private boolean isInteger(String str) { if (null == str || "".equals(str)) { return false; } Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); return pattern.matcher(str).matches(); } //判断浮点数(double和float) private

  • java将一个整数转化成二进制代码示例

    将一个整数转化成二进制的方法: 1 方法1:使用BigInteger类: @Test public void test1(){ BigInteger b=new BigInteger("10");//1010 System.out.println(b.toString(2));//0 b=new BigInteger("1"); System.out.println(b.toString(2));//1 b=new BigInteger("255"

  • java判断字符串是正整数的实例

    实例如下所示: public static boolean isPureDigital(String string) { if (isBlank(string)) return false; String regEx1 = "\\d+"; Pattern p; Matcher m; p = Pattern.compile(regEx1); m = p.matcher(string); if (m.matches()) return true; else return false; }

  • Java将一个正整数分解质因数的代码

    程序分析:对n进行分解质因数,应先找到一个最小的质数k,然后按下述步骤完成: 1.如果这个质数恰等于n,则说明分解质因数的过程已经结束,打印出即可. 2.如果n <> k,但n能被k整除,则应打印出k的值,并用n除以k的商,作为新的正整数你,重复执行第一步. 3.如果n不能被k整除,则用k+1作为k的值,重复执行第一步. 程序设计: public class exp2{ public exp2(){} public void fengjie(int n){ for(int i=2;i<=

  • 详解Java判断是否是整数,小数或实数的正则表达式

    经常会遇到这样的情况,需要判断一个字符串是否是一个合法的数,包括整数,小数或者实数. 网上查到很多文章大多是判断这个字符串是否全为数字,比如下面这段来自StringUtils的代码,可以看到,13.2这样的数字实际上会返回false,可是,他的确是一个数字. public static boolean isNumeric(String str) { if (str == null) { return false; } int sz = str.length(); for (int i = 0;

  • java整数(秒数)转换为时分秒格式的示例

    整数(秒数)转换为时分秒格式(xx:xx:xx) 复制代码 代码如下: // a integer to xx:xx:xx    public static String secToTime(int time) {        String timeStr = null;        int hour = 0;        int minute = 0;        int second = 0;        if (time <= 0)            return "00

  • 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); Syste

  • Java基础教程_判断语句if else

    与三元运算符相比: 好处:可以简化if else 代码 弊端 因为是一个运算符,所以运算玩必须要有一个结果 以上这篇Java基础教程_判断语句if else就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • Java基础教程之数组的定义与使用

    目录 一.数组的基本概念 二.数组的声明 三.数组的创建及初始化 1.数组的创建 2.数组的初始化 四.访问数组元素 五.for each 循环 六.数组的拷贝 七.数组排序 八.二维数组 总结 一.数组的基本概念 数组是一种数据类型,用来存储同一类型值的集合,它在内存中是一段连续的空间.通过一个整形下标(index,或者称之为索引)可以访问数组中的每一个值.例如,如果a是一个整型数组,a[i]就是一个下标为i的一个整数,数组是一种引用类型. 二.数组的声明 声明数组变量时,需要指出数组类型(数

  • Java基础教程之获取操作系统及浏览器信息

    目录 User Agent 的含义 浏览器的 UA 字串 UserAgentUtils.jar 通过(User-Agent)获取 浏览器类型,操作系统类型,手机机型 再给出一个: 总结 在生产环境下,我们需要关闭swagger配置,避免暴露接口的这种危险行为. User Agent 的含义 User Agent 中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本.CPU 类型.浏览器及版本.浏览器渲染引擎.浏览器语言.浏览器插件等. 一些网站常常通过判

  • java基础教程之拼图游戏的实现

    目录 前言 废话不多说,直接上效果图: 1.所需技术 2.具体实现 2.1 图片制作 2.2 创建项目 2.3 编码实现 总结 前言 大家在初学java的时候,大部分的代码都是在控制台上运行的.可能大家辛辛苦苦写了几十行代码,最终就只是在控制台输出一个字符,这个时候,心里肯定是拔凉拔凉的,心中那一朵编程的火花,就马上给扑灭了.我们都知道兴趣是最好的老师.为了拯救大家快要熄灭的小火花,小编在这里给大家带来使用java做个小游戏,并且通过做这个游戏,好好收悉一下面向对象的实际使用. 废话不多说,直接

  • Java基础教程之基本类型数据类型、包装类及自动拆装箱

    前言 我们知道基本数据类型包括byte, short, int, long, float, double, char, boolean,对应的包装类分别是Byte, Short, Integer, Long, Float, Double, Character, Boolean.关于基本数据类型的介绍可参考Java基础(一) 八大基本数据类型 那么为什么需要包装类? JAVA是面向对象的语言,很多类和方法中的参数都需使用对象,但基本数据类型却不是面向对象的,这就造成了很多不便. 如:List<in

  • Java基础教程之理解Annotation详细介绍

    Java基础之理解Annotation 一.概念  Annontation是Java5开始引入的新特征.中文名称一般叫注解.它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类.方法.成员变量等)进行关联. 更通俗的意思是为程序的元素(类.方法.成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且是供指定的工具或框架使用的. Annontation像一种修饰符一样,应用于包.类型.构造方法.方法.成员变量.参数及本地变量的声明语句中.

  • Java基础教程之对象的方法与数据成员

    在Java基础教程之从Hello World到面向对象一文中,我们初步了解了对象(object).对象中的数据成员表示对象的状态.对象可以执行方法,表示特定的动作. 此外,我们还了解了类(class).同一类的对象属于相同的类型(type).我们可以定义类,并使用该定义来产生对象. 我们进一步深入到对象.了解Java中方法与数据成员的一些细节. 调用同一对象的数据成员 方法可以调用该对象的数据成员.比如下面我们给Human类增加一个getHeight()的方法.该方法返回height数据成员的值

  • Java基础教程之接口的继承与抽象类

    在实施接口中,我们利用interface语法,将interface从类定义中独立出来,构成一个主体.interface为类提供了接口规范. 在继承中,我们为了提高程序的可复用性,引入的继承机制.当时的继承是基于类的.interface接口同样可以继承,以拓展原interface. 接口继承 接口继承(inheritance)与类继承很类似,就是以被继承的interface为基础,增添新增的接口方法原型.比如,我们以Cup作为原interface: 复制代码 代码如下: interface Cup

  • Java基础教程之组合(composition)

    我们已经尝试去定义类.定义类,就是新建了一种类型(type).有了类,我们接着构造相应类型的对象.更进一步,每个类型还应该有一个清晰的接口(interface),供用户使用. 我们可以在一个新类的定义中使用其他对象.这就是组合(composition).组合是在Java中实现程序复用(reusibility)的基本手段之一. 组合与"has-a" 一个对象是另一个对象的数据成员.比如我们看之前提到的充电电筒的例子: 一个充电电筒中的电池.LED灯.按钮-- 都可以是一个对象.我们可以定

随机推荐