Math类和StrictMath类源码详解
类的定义
public final class Math {
}
public final class StrictMath {
}
被final修饰的类不能被继承,即它不能拥有自己的子类
Math类会提供一些三角函数
对比
public static double sin(double a) {
return StrictMath.sin(a); // default impl. delegates to StrictMath
}
public static native double sin(double a);
Java平台有个用户和本地C代码进行互操作的API,称为Java Native Interface (Java本地接口)。
使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用。
这些函数的实现体在DLL中,JDK的源代码中并不包含,你应该是看不到的。对于不同的平台它们也是不同的。这也是java的底层机制,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的。
两个类最本质的区别-strictfp
public static strictfp double toRadians(double angdeg) {
// Do not delegate to Math.toRadians(angdeg) because
// this method has the strictfp modifier.
return angdeg / 180.0 * PI;
}
public static double toRadians(double angdeg) {
return angdeg / 180.0 * PI;
}
strictfp解释:
关于floor和floorMod方法
public static double ceil(double a) {
return StrictMath.ceil(a); // default impl. delegates to StrictMath
}
public static double floor(double a) {
return StrictMath.floor(a); // default impl. delegates to StrictMath
}
public static double ceil(double a) {
return floorOrCeil(a, -0.0, 1.0, 1.0);
}
public static double floor(double a) {
return floorOrCeil(a, -1.0, 0.0, -1.0);
}
private static double floorOrCeil(double a,
double negativeBoundary,
double positiveBoundary,
double sign) {
int exponent = Math.getExponent(a);
if (exponent < 0) {
/*
* Absolute value of argument is less than 1.
* floorOrceil(-0.0) => -0.0
* floorOrceil(+0.0) => +0.0
*/
return ((a == 0.0) ? a :
( (a < 0.0) ? negativeBoundary : positiveBoundary) );
} else if (exponent >= 52) {
/*
* Infinity, NaN, or a value so large it must be integral.
*/
return a;
}
// Else the argument is either an integral value already XOR it
// has to be rounded to one.
assert exponent >= 0 && exponent <= 51;
long doppel = Double.doubleToRawLongBits(a);
long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
if ( (mask & doppel) == 0L )
return a; // integral value
else {
double result = Double.longBitsToDouble(doppel & (~mask));
if (sign*a > 0.0)
result = result + sign;
return result;
}
}
x = Math.getExponent(y)相当于y = Math.pow(2, x),2^x
double exponent = Math.getExponent(1);//无偏差指数
如果参数为NaN或无穷大,那么结果是Float.MAX_EXPONENT+1。
如果参数是零或小于正常值,那么结果是Float.MIN_EXPONENT-1。
关于0和0L
java的内存体制
example:
long fw = 10000000000L;
实际上内存中fw只是一个long类型的变量,它存在于向stack(栈)中,数值并不在其中存放,它指向heap(堆)中另一块真正存放数值的内存,加L的目的就是为了让heap中也创建一块long类型所需要的内存,用来来放数值。
所以说=前后两者其实是在不同的两块内存,只不过有个无形的指针将两者连接起来了。
不加的后果:
public static int floorMod(int x, int y) {
int r = x - floorDiv(x, y) * y;
return r;
}
public static long floorMod(long x, long y) {
return x - floorDiv(x, y) * y;
}
public static int floorDiv(int x, int y) {
int r = x / y;
// if the signs are different and modulo not zero, round down
if ((x ^ y) < 0 && (r * y != x)) {
r--;
}
return r;
}
java中求模使用的是Math.floorMod(被除数, 除数)方法
当被除数和除数同号的时候,求余和取模得到的结果是相等的
求余得到商的过程是先用绝对值求商再添上正负号
求模得到商的过程是用绝对值求商的值+1再添正负号,能整除的除外。
求余过程中:
余数的正负号取决于被除数,被除数为正则为正,被除数为负则为负
求模过程中:
模的正负号取决于除数,除数为正则为正,除数为负责为负
public static int abs(int a) {
return (a < 0) ? -a : a;
}
public static float abs(float a) {
return (a <= 0.0F) ? 0.0F - a : a;
}
public static double abs(double a) {
return (a <= 0.0D) ? 0.0D - a : a;
}
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
public static float max(float a, float b) {
if (a != a)
return a; // a is NaN
if ((a == 0.0f) &&
(b == 0.0f) &&
(Float.floatToRawIntBits(a) == negativeZeroFloatBits)) {
// Raw conversion ok since NaN can't map to -0.0.
return b;
}
return (a >= b) ? a : b;
}