JAVA基础之三:运算操作符
来源:互联网 发布:中国乒乓球 知乎 编辑:程序博客网 时间:2024/06/07 19:36
原文链接:http://happyshome.cn/blog/java/basics/operations.html
本文中主要介绍Java中的运算操作。 如何正确的使用运算符,防止溢出是每个程序员的责任。
1. 算术运算
Java支持以下的算术运算:
3.3 * 1.0 → 3.3/除法expr1 / expr21 / 2 → 0
1.0 / 2.0 → 0.5%取余expr1 % expr25 % 2 → 1
-5 % 2 → -1
5.5 % 2.2 → 1.1+加法(正号)expr1 + expr2
+expr1 + 2 → 3
1.1 + 2.2 → 3.3-减法(负号)expr1 - expr2
-expr1 - 2 → -1
1.1 - 2.2 → -1.1
2. 算术表达式
对于下面的表达式:
转化为编码(1+2*a)/3 + (4*(b+c)*(5-d-e))/f - 6*(7/g+h),需要注意的不能省略乘号(*)。
优先级:
- 乘法(*),除法(/)和取余(%)优先于加法(+)和减法(-)运算,例如1+2*3-4/2可以表示为1+(2*3)-(4/2)。
- 正号(+)和负号(-)拥有更高级别。
- 括号()拥有最高级别,常用来调整运算顺序。
- 对于同级别运算符号,表达式结果从左到右计算,例如1+2-3+4等价于((1+2)-3)+4,1*2%3/4等价于((1*2)%3)/4。
3. 混合类型运算
算术运算仅适用于基本类型:byte, short, int, long, float, double和char,其中不包括boolean。
如果两个操作数的类型是int/long/float/double, 运算操作会直接使用此类型进行计算,例如int 5 + int 6 → int 11; double 2.1 + double 1.2 → double 3.3。
值得注意的是对于int的除法运算,计算结果会被截断,例如1/2 → 0而不是0.5。
如果两个操作数的类型是byte,short或者char,运算操作会使用int类型进行计算,char会被转化为16位无符号整数,例如byte 127 + byte 1 → int 127 + int 1 → int 128。
如果两个操作数属于不同的类型,较小的类型会被隐式的转换成较大的类型,运算操作会使用较大的类型进行计算。
举例说明:
- int/double → double/double → double,1/2 → 0, 1.0/2.0 → 0.5, 1.0/2 → 0.5, 1/2.0 → 0.5。
- char + float → int + float → float + float → float。
- 9 / 5 * 20.1 → (9 / 5) * 20.1 → 1 * 20.1 → 1.0 * 20.1 → 20.1 (你可能不会想到这个答案)。
- byte 1 + byte 2 → int 1 + int 2 → int 3 (结果是int,不是byte)。
二元运算操作对于类型的转换概括如下:
- 如果其中一个操作数是double,另一个操作数默认转为double。
- 如果其中一个操作数是float,另一个操作数默认转为float。
- 如果其中一个操作数是long,另一个操作数默认转为long。
- 其余的操作数默认的转为int。
一元运算操(正号、负号)对于类型的转换概括如下:
- 如果操作数是double,float,long或者int,不需要转换。
- 其余的如果是byte,short或char,会默认转换为int。
举例说明:
byte b1 = 1;byte b2 = -b1; // 编译会出错, 因为-b1会返回int,不能转换成byte
取余运算符
为了计算余数会重复的运行减法运算,直到差值的绝对值小于右操作数的绝对值,举例说明:
- -5 % 2 ⇒ -3 % 2 ⇒ -1
- 5.5 % 2.2 ⇒ 3.3 % 2.2 ⇒ 1.1
指数
在Java中是没有指数运算符的,你看到的'^'运算符是异或,不过你可以使用Math.exp(X,Y)进行指数的运算。
4. 向上溢出/向下溢出
研究下面的代码并解释输出输出:
/* * "int"溢出说明 */public class OverflowTest { public static void main(String[] args) { // int取值范围[-2147483648, 2147483647] int i1 = 2147483647; // int最大值 System.out.println(i1 + 1); // -2147483648 (溢出) System.out.println(i1 + 2); // -2147483647 System.out.println(i1 * i1); // 1 int i2 = -2147483648; // int最小值 System.out.println(i2 - 1); // 2147483647 (溢出) System.out.println(i2 - 2); // 2147483646 System.out.println(i2 * i2); // 0 }}
对于运算过程中的溢出,Java不会发出错误或者警告信息,但会产生不正确的结果。
另一方面整数除法会产生截断的整数,我们称之为向下溢出,例如1/2 → 0,而不是0.5。
做为程序员你有责任去检查编程中的溢出。
这时候我们也许会问,为什么计算机不去标记溢出?由于历史的原因, 当时处理器很慢,检查溢出会消耗性能。
5. 类型转换
在Java中,如果将double或float数据赋值给int变量会产生编译错误。
double d = 3.5;int i;i = d; // 编译错误int sum = 55.66f; // 编译错误
显示类型转换和类型转换
double赋值给int变量,你需要使用显示类型转换,形式为(int)value,返回的结果是被截断的int数据,举例说明:
double d = 3.5;int i;i = (int) d; // 将double类型的3.5转换成int类型的3,之后赋值给i
类型转换只需要一个操作数,Java中有两种类型转换:
- 以(new-type)操作数的形式进行显示类型转换。
- 如果没有精度缺失,编译器自动的会进行隐示类型转换。
int i = 3;double d;d = i; // 正确, 不需要进行类型转换,d=3.0
d = (double) i; // 也可以使用显示类型转换double aDouble = 55; // 编译器会自动的将int 55转换成double 55.0double nought = 0; // 编译器会自动的将int 0转换成double 0.0 // 值得注意的是int 0和double 0.0是不同的
下面的这幅图展示了编译器隐示类型转换的顺序,转换规则是将小类型晋升为大类型,这样做可以防止精度缺失。降级类型需要显示类型转换,精度会缺失,值得注意的是char会被视作16位无符号整数,取值范围[0, 65535],boolean类型不支持转换。
例子,计算从1到100的平均值,仔细研究下面的代码
public class Sum1To100 { public static void main(String[] args) { int sum = 0; double average; int number = 1; while (number <= 100) { sum += number; // sum最后的结果为int 5050 ++number; } average = sum / 100; // average = 50.0而不是50.5 System.out.println("Average is " + average); // 平均值为50.0 }}
这是因为sum与100都是int类型,二者相除返回的是被截断的int,如果想得到正确的结果,你可以采用下面的方式:
average = (double)sum / 100; // 进行除法运算前显示的将sum转成double类型average = sum / (double)100; // 进行除法运算前显示的将100转成double类型average = sum / 100.0;average = (double)(sum / 100); // 这种做法是错误的,你知道是什么原因吗?
6. 复合赋值运算
除了前面介绍的常用的赋值运算=,Java还提供了其它的复合赋值运算:
将右操作数赋值给左操作数var = exprx = 5;+=
复合加法运算
var += expr等价于var = var + exprx += 5;
等价于x = x + 5-=复合减法运算var -= expr
等价于var = var - exprx -= 5;
等价于x = x - 5*=复合乘法运算var *= expr
等价于var = var * exprx *= 5;
等价于x = x * 5/=复合除法运算var /= expr
等价于var = var / exprx /= 5;
等价于x = x / 5%=复合取余运算var %= expr
等价于var = var % exprx %= 5;
等价于x = x % 5
7. 自增/自减
对于一元运算自增(++)和自减(--),适用于除boolean类型以外的其它 基本类型byte, short, char, int, long, float和double。
x++或++x等价于x += 1或x = x + 1int x = 5;
x++;
++x;--原数值减1
x--或--x等价于x -= 1或x = x - 1int y = 6;
y--;
--y;
自增和自减都是基于自身的操作,例如x++自增后重新返回给x。
自增/自减操作符号可以放置于操作数之前,也可以放在操作数之后,但是两者有着不同的意义。
如果这些运算符基于自身操作,运算符前置和后置具有同样的效果,例如++x和x++,因为表达式的值会被忽略。
如果用于其它的操作,例如y=x++或y=++x,对于y值来说运算符前置和后置有不同的值。
首先var加1,计算结果使用vary = ++x;
等价于x=x+1; y=x;var++自增
首先计算结果使用var,接着var加1y = x++;
等价于oldX=x; x=x+1; y=oldX;--var自减y = --x;
等价于x=x-1; y=x;var--自减y = x--;
等价于oldX=x; x=x-1; y=oldX;
8. 关系和逻辑运算符
很多时候,你需要对两个值进行比较之后,才会进行某些操作,举例如果mark值大于等于50,输出"PASS!"。
Java提供了6种比较运算符,经过比较运算后返回布尔值即true或false。
每个比较运算符需要两个操作数,正确的写法:x > 1 && x < 100,错误的写法 1 < x < 100, 这里面&&表示与操作。
Java提供了4种基于boolean的逻辑运算,按照优先级顺序如下:
真值表如下:
举例说明:
// 如果x取值范围在[0,100],返回true(x >= 0) && (x <= 100)// 如果x取值范围不在[0,100],返回true(x < 0) || (x > 100)!((x >= 0) && (x <= 100))// 计算是否为闰年:某年被4但不能被100整除,或者被400整除((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)
练习:研究下面的程序并解释输出。
public class RelationalLogicalOpTest { public static void main(String[] args) { int age = 18; double weight = 71.23; int height = 191; boolean married = false; boolean attached = false; char gender = 'm'; System.out.println(!married && !attached && (gender == 'm')); System.out.println(married && (gender == 'f')); System.out.println((height >= 180) && (weight >= 65) && (weight <= 80)); System.out.println((height >= 180) || (weight >= 90)); }}
练习:
根据提供的日期:年、月(1-12)和日(1-31),计算该日期是否早于1582年10月15日。
运算符优先级
优先级由高到低:'!', '^','&&','||',编程中如果不确定,请使用括号()。
System.out.println(true || true && false); // true (和下面的一样)System.out.println(true || (true && false)); // trueSystem.out.println((true || true) && false); // falseSystem.out.println(false && true ^ true); // false (和下面的一样)System.out.println(false && (true ^ true)); // falseSystem.out.println((false && true) ^ true); // true
短路操作符
逻辑与(&&)和逻辑或(||)被称为短路操作符,这意味计算结果如果可以通过左操作数来确定,那么右操作数会被忽略,例如false && ...会返回false,true || ...会返回true。
- JAVA基础之三:运算操作符
- Java基础之三目运算符,if,switch
- java基础之运算符
- JAVA基础之运算符
- java基础之运算符
- Java基础之运算符
- java基础之运算符
- java基础之运算符
- Java基础之运算符
- Java基础之运算符
- java基础之运算符
- Java基础之运算符
- C++基础之三目运算符
- java三目运算符操作注意事项
- Python基础之运算操作符总结
- Java学习笔记之java基础语法,运算符(三)
- Java基础之Java运算符大百科
- 黑马程序员——Java基础(三)之运算符、键盘录入、流程控制语句
- 每隔一段时间就从服务端下载数据使用sql语句实现
- Ubuntu下ifconfig出来都是星号
- arm-linux-gcc编译工具的安装
- 码农小汪-设计模式-抽象工厂模式
- VC 字符串转化和分割
- JAVA基础之三:运算操作符
- Fragment详解
- SGU 117 Counting(快速幂)
- poj1087(最大流)
- 如何下载android-cts-5.0_r5源码
- 专题二1001
- 《网络工程师》 Part4 局域网与城域网
- C++创建文件夹
- OpenGL调节屏幕的宽高比