您的位置:首页 > 编程语言 > Java开发

java的运算符和strictfp关键字

2014-04-26 22:55 183 查看
operators也就是运算符,其实和c/c++大同小异,不过也有细微的差别。先介绍最基本的运算符吧;+,-,*,/,%

1、对于除法/,当两边的操作数是整数,那么就是整数除法,否则是浮点数,就是浮点除法floating-point division,最后的%是取余运算,我们通常叫模运算。这都很熟悉的。

例子;

System.out.println(1 / 0);
打印;Exception in thread "main" java.lang.ArithmeticException: / by zero at coreJava.PrimitiveType.main(PrimitiveType.java:24),出现了除0异常。
System.out.println(1.0 / 0);打印;Infinity
这是需要注意的地方!浮点运算的除0,不抛出异常,得到一个无穷大的结果。

2、复合运算符;+=等,和c系列一样,把运算符放到赋值=的紧贴的左边即可。int x = x + 1;等价于int x += 1;

3、strictfp关键字的介绍

对于java的设计目标—在浮点运算中,一次编译到处运行的可移植性,并且结果不变的实现是很困难的,double类型是64位来存储一个数值,但是一些处理器处理浮点运算是80位的,比如Intel系列的,在计算的中间步骤,会将80位的结果来计算,到最后的步骤时,截断为64位,这样的话,可以避免指数溢出的问题,并且结果也更加的精确,但是这样做的结果可能始终和在64位机器上运算的结果不一致,这样就无法实现移植性,那么jvm规范就规定,必须把中间的计算结果截断了!不能等到最后去截断!虽然可以实现移植性,不过,这样做的话有可能产生溢出,并且运算速度降低(因为截断消耗时间),这也是个矛盾所在,jvm规范也最后承认了这点,那就是完美的性能和结果与理想的移植性的矛盾!最终jvm规范妥协了,规定默认的时候中间运算结果可以不截断,但是方法或者类,在显式的使用strictfp关键字的时候,必须严格的执行浮点运算的计算原理,中间结果必须截断,来得到可复用移植的结果。用的场合和机会不是很多,一般情况下不用深究。以后在细细的谈谈浮点数运算的机器表示和实现吧……

自增,自减运算符i++和--;

1、注意它改变的是变量本身的值,故不可以声明为常量,比如;1++;这是错误的!

2、注意计算顺序和前缀后缀的区分,前缀先change,后运算。后缀先运算后change。例如

int x = 1;
int y = 1;
int m = 2 * x++;
int n = 2 * ++y;
System.out.println("m = " + m + " " + "n = " + n + " " + "x = " + x
+ " " + "y = " + y);
打印;m = 2 n = 4 x = 2 y = 2

3、强烈建议自增减类运算符单独写在表达式外边,不要写在表达式的内部,那样的话,整个程序内写多了会看着心烦,产生混淆和bug变得多多!

关系运算符和boolean运算符;判等==,不等!=,小于<,大于>,小于等于<=,大于等于>=,逻辑与&&,逻辑或||,逻辑非!,非~,或|,与&,异或^,三元?:,左移《,带符号右移》,无符号右移>>>

1、需要注意短路操作,逻辑运算符;&&和||,均是只看第一个表达式即可,前者是一假则假,后者是一真则真。举例;

int x = 11;
if (x != 0 && x > 10) {
System.out.println("ok");
}
打印;ok

但是当左边变为x==0,那就假了。

if (x == 0 && x > 10) {
System.out.println("true");
}else {
System.out.println("false");
}打印;false
2、对于三元运算符,用的不是很多,用来比较两个表达式而做出选择。例如;

int x = 11;
int y = 10;
System.out.println(x > y ? x : y);打印;11
3、移位运算符;与&,或|,^异或,非!,若他们在位模式下工作,通过这些运算符可以实现屏蔽数位的职责。当然也可以进行逻辑判断,&和|如果用在布尔运算中,和1中双与,双或类似,只是没有短路操作,必须两个表达式都判断真假,结果也是布尔的。在二进制的位模式下遵循法则;&一假则假,|一真则真,^相同则假,原理是通过使用2的幂次方来起到屏蔽的作用,只剩下某个想要的位。如例子;

int x = 11;//二进制是1011
//注意这些运算符是在位模式下运算的,括号里启到屏蔽作用,8的二进制是1000,
int result = (x & 8) / 8;//后三位屏蔽了,8除以8最后得到1
System.out.println(result);
再看一例;

int a = 1;
int b =2;
if (a < 0 && b < a--) {
System.out.println("ok");
}
System.out.println(a);打印a的值是1,短路了。
int a = 1;
int b = 2;
if (a < 0 & b < a--) {
System.out.println("ok");
}
System.out.println(a);打印a的值是0,说明两个表达式都执行了!!!记住区别。

4、特别注意逻辑移位和算数移位;》右移,《左移,符号的左边是操作数,右边是参数。对于带符号右移》符号,如果是正数,则高位补0,负数则符号位不变,左边补上符号位1(因为0正1负)。对于带符号左移《,则是低位直接补充0即可,很简单。他们在位模式下进行数位的屏蔽作用。且《左移一位等价于乘2一次,对于2的幂次整数,》右移一位等价于除2一次。
// 打印4,乘2
System.out.println(2 << 1);
// 打印1
System.out.println(2 >> 1);
// 打印-4
System.out.println(-2 << 1);
// 打印-1
System.out.println(-2 >> 1);
// 打印-6
System.out.println(-3 << 1);
// 这里说右移一次就是除一次2是错误的,前提是2的幂次数
// 打印2
System.out.println(5 >> 1);
// 打印-2
System.out.println(-3 >> 1);
要知道java中的int是32位,正数以原码的形式存储,负数以补码的形式存储。且负数的补码等于原码的反码加1,而正数的原码补码反码同一。

5、>>>无符号右移运算符,高位补充0即可,带符号》右移运算符用符号位填充高位!且没有<<<。

// 打印2147483647
System.out.println(-2 >>> 1);
// 打印1,无符号就是正数
System.out.println(2 >>> 1);
java是没有无符号数的,也就是说java都是有符号的参与运算!都适用!c++要区分有符号和无符号。无符号右移,不论正负,高位始终补充0,地位舍弃!当我们要作位移的原始值并非代表数值时(例如:表示颜色图素的值),可能就会需要使用此种无符号的位移。

6、对于符号右边的参数,时刻注意;int型需要先模32,long型需要先模64。比如1《35和1《3等价,因为35模32是3,他们都等价左移3位,1的二进制模式下左移三位就等于8。例如;

System.out.println(1 << 3);
// 打印8
System.out.println(1 << 35);
//打印8
System.out.println(1L << 3);
//打印34359738368
System.out.println(1l << 35);
//打印1
System.out.println(1l << 64);
//打印2
System.out.println(1l << 65);
注意;后几个都是long型。

7、按位取反~运算符

System.out.println(~1);
打印;-2

1默认32位int型,是正数,0000 0000 0000 0000 0000 0000 0000 0001,进行按位取反运算之后得到 1111 1111 1111 1111 1111 1111 1111 1110,结果变为了负数,负数是按照补码存储,即这个数是特么的补码!!!!那么按照原码的反码(符号位不变)再加上1为补码的逆运算得出;1000 0000 0000 0000 0000 0000 0000 0010,就是-2,即原数加1,再取负!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息