一、运算符
整数被0除会产生一个异常,而浮点数被0除将会得到无穷大或者NaN结果。
可移植性是 Java 语言的设计目标之一 ,无论在哪个虚拟机上运行,同一运算应该得到同样的结果。对于浮点数的算术运算,实现这样的可移植性是相当困难的。double类型使用64位存储一个数值, 而有些处理器使用80位浮点寄存器这些寄存器增加了中间过程的计算精度。
例如:以下运算:double w = x * y / z; 很多 Inte丨处理器计算 x * y,并且将结果存储在 80 位的寄存器中, 再除以 z 并将结果截断为64位,这样可以得到一个更加精确的计算结果,并且还能够避免产生指数溢出。但是,这个结果可能与始终在 64 位机器上计算的结果不一样。因此,Java 虚拟机的最初规范规定所有的中间计算都必须进行截断这种行为遭到了数值计算团体的反对。截断计算不仅可能导致溢出,而且由于截断操作需要消耗时间,所以在计算速度上实际上要比精确计算慢。为此,Java程序设计语言承认了最优性能与理想结果之间存在的冲突,并给予了改进。
在默认情况下,虚拟机设计者允许对中间计算结果采用扩展的精度。但是,对于使用 strictfp关键字标记的方法必须使用严格的浮点计算来生成可再生的结果。
例如:可以把 main 方法标记为 public static strictfp void main(String[] args) 于是,在 main 方法中的所有指令都将使用严格的浮点计算。如果将一个类标记为 strictfp, 这个类中的所有方法都要使用严格的浮点计算。 实际的计算方式将取决于 Intel 处理器的行为。在默认情况下,中间结果允许使用扩展的指数,但不允许使用扩展的尾数(Intel 芯片在截断尾数时并不损失性能)。因此,这两种方式的区别仅仅在于采用默认的方式不会产生溢出,而采用严格的计算有可能产生溢出。
1.1、数学函数与常量
“%”运算和floorMod方法的区别(及取余运算和模运算的区别)
对于整型数a,b来说,取模运算或者求余运算的方法都是: 1.求整数商: c = a/b; 2.计算模或者余数: r = a - c*b. 求模运算和求余运算在第一步不同: 取余运算在取c的值时,向0 方向舍入(fix()函数);而取模运算在计算c的值时,向负无穷方向舍入(floor()函数)。 例如:计算-7 Mod 4 那么:a = -7;b = 4; 需要注意的是:%运算结果的符号和a的符号一致,mod运算结果的符号和b的符号一致。 另外各个环境下%运算符的含义不同,比如c/c++,java 为取余,而python则为取模。 使用Math函数时,直接在源文件顶部添加import static java.lang.Math.*;即可 在 Math 类中,为了达到最快的性能,所有的方法都使用计算机浮点单元中的例程. 如果得到一个完全可预测的结果比运行速度更重要的话,那么就应该使用 StrictMath 类。 1.2、数值类型之间的转化 合法转化:图中有 6 个实心箭头,表示无信息丢失的转换;有 3 个虚箭头, 表示可能有精度 损失的转换。
当使用上面两个数值进行二元操作时(例如 n + f,n 是整数, f 是浮点数,) 先要将两个操作数转换为同一种类型,然后再进行计算。
如果两个操作数中有一个是 double 类型, 另一个操作数就会转换为 double 类型。
否则,如果其中一个操作数是 float 类型,另一个操作数将会转换为 float 类型。
否则, 如果其中一个操作数是 long 类型, 另一个操作数将会转换为 long 类型。
否则, 两个操作数都将被转换为 int 类型。
强制类型转换:
通过截断小数部分将浮点值转化为整型。
例如:(byte)300 = 44;
因为 300 = 0b1 0010 1100。
如果想对浮点数进行舍人运算, 以便得到最接近的整数(在很多情况下,这种操作更有用)那就需要使用 Math_ round 方法:
long round(double d);
int round(float f);
round() 方法返回一个最接近的 int、long 型值,四舍五入。
round 表示"四舍五入",算法为Math.floor(x+0.5) ,即将原来的数字加上 0.5 后再向下取整,所以Math.round(11.5) 的结果为 12,Math.round(-11.5) 的结果为 -11。