基本的运算符有 +, -, , /, % 。其中需要注意的是:整数被 0 除将会产生一个异常,而浮点数被 0 除将会得到 无穷大 或 NaN 结果
对于浮点数运算,很难做到每个处理器上的结果都相同,这是因为 double 类型使用 64 位存储一个数值,而有些处理器使用 80 位浮点寄存器。这些寄存器增加了中间过程的计算精度。从而使计算更加准确。但这样准确的结果是 64 位机器算不出来的。
为了处理这样的差异。在 Java 中,*默认情况
是按照精度优先,也就是发挥每个处理器的优势。也可以指定 strictfp 关键字来规定 Java 来使用严格的浮点计算。也就是保证每个处理器算出的精度一致。

  1. public static strictfp void main(String[] args)
  2. // 在这个方法中的所有指令都将使用严格的浮点运算
  3. // 也可以将一个类标记为 strictfp , 那这个类中的所有方法都要使用严格的浮点计算

数学函数与常量

Math.sqrt(x) ,是计算一个数组的平方根。
Math.pow(x, a) ,是计算 x 的 a 次幂( x )。其中参数和返回值都是 double 类型。
Math.floorMod() ,是一个解决整数余数的问题。对于表达式 n % 2 ,正常情况都没有问题,奇数为 1 ,偶数为 0 。但是,如果 n 为负数,一切都乱套了。所以我们要使用 ((n % 2) + 2) % 2 来解决这个问题。但是现在你可以使用 Math.floorMod(n, 2) 来解决这个问题。遗憾的是,对于负除数,floorMod 会得到负数结果,不过这种情况在实际中很少出现。
Math.PI, Math.E 表示 π 和 e 常量的近似值。
需要注意的是,Math 类中的方法,大多是静态方法。
通常情况下,Math 类更多的是追求处理器的性能而不是完全可预测的结果,如果可预测的结果(每个机器上的输出都一样,当可能精度不高,也就是算不准)对你来说更重要,你可以使用 StrictMath 类,它使用 fdlibm 实现算法,以确保在所有平台上得到相同的结果。

数值类型之间的转换

Type_conversion
精度损失举个例子:

  1. int n = 123456789;
  2. float f = n; // f is 1.23456792E8 // 注意后两位

当使用两个数值类型不一样进行二元操作时(例如 n + f ,n 是整数,f 是浮点数),先要将两个操作数转换为同一种类型,然后再进行计算。

  • 如果两个操作数中有一个是 double 类型,另一个操作数就会转换为 double 类型。
  • 否则,如果其中一个操作数是 float 类型,另一个操作数将会转换为 float 类型。
  • 否则,如果其中一个操作数是 long 类型,另一个操作数将会转换为 long 类型。
  • 否则,两个操作数都将被转换为 int 类型。

也就是 double -> float -> long -> int 这样的优先级。也可以看成是 浮点数 -> 整数 的优先级。

强制类型转换

我们知道,在数据运算时,如果有更优先的类型如 double ,int 会自动的转换成 double 类型。如果你想都使用 int 来计算。可以使用强制类型转换。

  1. double x = 9.997;
  2. int nx = (int) x; // 9

使用强制类型转换需要注意的是,会发生信息丢失的可能性。比如, (byte) 300 实际为 44 。
如果使用结合运算符,其类型与左侧操作数的类型不同,就会发生强制类型转换:

  1. x += 3.5;
  2. // like
  3. x = (int) (x + 3.5);

关系运算符

在 Java 中,&&|| 是按照短路的方式来计算的。

  1. x != 0 && 1 / x > x + y // no division by 0

因为有 x != 0&& 的存在,后面的表达式中的 x 永远都不可能为 0 。

位运算符

&, and, 且
|, or, 或
&, xor, 异或
~, not, 按位取反
<<, 左移
>>, 右移,高位有用符号位填充
>>>, 无符号右移,高位会用 0 填充
值得注意的是:
& 和 | 与上面的关系运算符 && 和 || 不一样,他们不采用短路的方式来求值。
移位运算符(三个)的右操作数要完成模 32 的运算(long 就模 64 )。如,1 << 35 等于 1 << 3 , 1 << (35 % 32)

枚举类型

当变量的取值在有限个的集合内,可以使用枚举类型。

  1. enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };

然后就可以使用它。

  1. Size s = Size.MEDIUM;

Size 类型的变量只能存储这个类型声明中给定的某个枚举值,或者null值,null表示这个变量没有设置任何值。