Math 类 、BigDecimal

Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。

与 StrictMath 类的某些数学方法不同,并非 Math 类所有等价函数的实现都定义为返回逐位相同的结果。此类在不需要严格重复的地方可以得到更好的执行。

默认情况下,很多 Math 方法仅调用 StrictMath 中的等价方法来完成它们的实现。建议代码生成器使用特定于平台的本机库或者微处理器指令(可用时)来提供 Math 方法更高性能的实现。这种更高性能的实现仍然必须遵守 Math 的规范。

实现规范的质量涉及到两种属性,即返回结果的准确性和方法的单调性。浮点 Math 方法的准确性根据 ulp(units in the last place,最后一位的进退位)来衡量。对于给定的浮点格式,特定实数值的 ulp 是包括该数值的两个浮点值的差。当作为一个整体而不是针对具体参数讨论方法的准确性时,引入的 ulp 数用于任何参数最差情况下的误差。如果一个方法的误差总是小于 0.5 ulp,那么该方法始终返回最接近准确结果的浮点数;这种方法就是正确舍入。一个正确舍入的方法通常能得到最佳的浮点近似值;然而,对于许多浮点方法,进行正确舍入有些不切实际。相反,对于 Math 类,某些方法允许误差在 1 或 2 ulp 的范围内。非正式地,对于 1 ulp 的误差范围,当准确结果是可表示的数值时,应该按照计算结果返回准确结果;否则,返回包括准确结果的两个浮点值中的一个。对于值很大的准确结果,括号的一端可以是无穷大。除了个别参数的准确性之外,维护不同参数的方法之间的正确关系也很重要。因此,大多数误差大于 0.5 ulp 的方法都要求是半单调的:只要数学函数是非递减的,浮点近似值就是非递减的;同样,只要数学函数是非递增的,浮点近似值就是非递增的。并非所有准确性为 1 ulp 的近似值都能自动满足单调性要求。

方法摘要:

abs(double a) 
返回 double 值的绝对值。 
abs(float a) 
返回 float 值的绝对值。 
abs(int a) 
返回 int 值的绝对值。 
abs(long a) 
返回 long 值的绝对值。 
acos(double a) 
返回一个值的反余弦;返回的角度范围在 0.0 到 pi 之间。 
asin(double a) 
返回一个值的反正弦;返回的角度范围在 -pi/2 到 pi/2 之间。 
atan(double a) 
返回一个值的反正切;返回的角度范围在 -pi/2 到 pi/2 之间。 
atan2(double y, double x) 
将矩形坐标 (x, y) 转换成极坐标 (r, theta),返回所得角 theta。 
cbrt(double a) 
返回 double 值的立方根。 
ceil(double a) 
返回最小的(最接近负无穷大)double 值,该值大于等于参数,并等于某个整数。 
copySign(double magnitude, double sign) 
返回带有第二个浮点参数符号的第一个浮点参数。 
copySign(float magnitude, float sign) 
返回带有第二个浮点参数符号的第一个浮点参数。 
cos(double a) 
返回角的三角余弦。 
cosh(double x) 
返回 double 值的双曲线余弦。 
exp(double a) 
返回欧拉数 e 的 double 次幂的值。 
expm1(double x) 
返回 ex -1。 
floor(double a) 
返回最大的(最接近正无穷大)double 值,该值小于等于参数,并等于某个整数。 
getExponent(double d) 
返回 double 表示形式中使用的无偏指数。 
getExponent(float f) 
返回 float 表示形式中使用的无偏指数。 
hypot(double x, double y) 
返回 sqrt(x2 +y2),没有中间溢出或下溢。 
IEEEremainder(double f1, double f2) 
按照 IEEE 754 标准的规定,对两个参数进行余数运算。 
log(double a) 
返回 double 值的自然对数(底数是 e)。 
log10(double a) 
返回 double 值的底数为 10 的对数。 
log1p(double x) 
返回参数与 1 之和的自然对数。 
max(double a, double b) 
返回两个 double 值中较大的一个。 
max(float a, float b) 
返回两个 float 值中较大的一个。 
max(int a, int b) 
返回两个 int 值中较大的一个。 
max(long a, long b) 
返回两个 long 值中较大的一个。 
min(double a, double b) 
返回两个 double 值中较小的一个。 
min(float a, float b) 
返回两个 float 值中较小的一个。 
min(int a, int b) 
返回两个 int 值中较小的一个。 
min(long a, long b) 
返回两个 long 值中较小的一个。 
nextAfter(double start, double direction) 
返回第一个参数和第二个参数之间与第一个参数相邻的浮点数。 
nextAfter(float start, double direction) 
返回第一个参数和第二个参数之间与第一个参数相邻的浮点数。 
nextUp(double d) 
返回 d 和正无穷大之间与 d 相邻的浮点值。 
nextUp(float f) 
返回 f 和正无穷大之间与 f 相邻的浮点值。 
pow(double a, double b) 
返回第一个参数的第二个参数次幂的值。 
random() 
返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。 
rint(double a) 
返回最接近参数并等于某一整数的 double 值。 
round(double a) 
返回最接近参数的 long。 
round(float a) 
返回最接近参数的 int。 
scalb(double d, int scaleFactor) 
返回 d × 2scaleFactor,其舍入方式如同将一个正确舍入的浮点值乘以 double 值集合中的一个值。 
scalb(float f, int scaleFactor) 
返回 f × 2scaleFactor,其舍入方式如同将一个正确舍入的浮点值乘以 float 值集合中的一个值。 
signum(double d) 
返回参数的符号函数;如果参数为 0,则返回 0;如果参数大于 0,则返回 1.0;如果参数小于 0,则返回 -1.0。 
signum(float f) 
返回参数的符号函数;如果参数为 0,则返回 0;如果参数大于 0,则返回 1.0;如果参数小于 0,则返回 -1.0。 
sin(double a) 
返回角的三角正弦。 
sinh(double x) 
返回 double 值的双曲线正弦。 
sqrt(double a) 
返回正确舍入的 double 值的正平方根。 
tan(double a) 
返回角的三角正切。 
tanh(double x) 
返回 double 值的双曲线余弦。 
toDegrees(double angrad) 
将用弧度表示的角转换为近似相等的用角度表示的角。 
toRadians(double angdeg) 
将用角度表示的角转换为近似相等的用弧度表示的角。 
ulp(double d) 
返回参数的 ulp 大小。 
ulp(float f) 
返回参数的 ulp 大小。

BigDecimal简介

BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负scale 次幂。因此,BigDecimal表示的数值是(unscaledValue × 10-scale)。

构造函数(主要测试参数类型为double和String的两个常用构造函数)

       BigDecimal aDouble =new BigDecimal(1.22);
        System.out.println("construct with a double value: " + aDouble);
        BigDecimal aString = new BigDecimal("1.22");
         System.out.println("construct with a String value: " + aString);

输出结果如下:

         construct with a doublevalue:1.2199999999999999733546474089962430298328399658203125
         construct with a String value: 1.22

1、参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。

2、另一方面,String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用String构造方法。

        BigDecimal a =new BigDecimal("1.22");
        System.out.println("construct with a String value: " + a);
        BigDecimal b =new BigDecimal("2.22");
        a.add(b);
        System.out.println("aplus b is : " + a);
        我们很容易会认为会输出:
        construct with a Stringvalue: 1.22
        a plus b is :3.44
        但实际上a plus b is : 1.22

add(BigDecimal augend)方法

      public BigDecimal   add(BigDecimal augend) {
          long xs =this.intCompact; //整型数字表示的BigDecimal,例a的intCompact值为122
          long ys = augend.intCompact;//同上
          BigInteger fst = (this.intCompact !=INFLATED) ?null :this.intVal;//初始化BigInteger的值,intVal为BigDecimal的一个BigInteger类型的属性
          BigInteger snd =(augend.intCompact !=INFLATED) ?null : augend.intVal;
          int rscale =this.scale;//小数位数

          long sdiff = (long)rscale - augend.scale;//小数位数之差
          if (sdiff != 0) {//取小数位数多的为结果的小数位数
              if (sdiff < 0) {
                 int raise =checkScale(-sdiff);
                 rscale =augend.scale;
                 if (xs ==INFLATED ||
                     (xs = longMultiplyPowerTen(xs,raise)) ==INFLATED)
                     fst =bigMultiplyPowerTen(raise);
                }else {
                   int raise =augend.checkScale(sdiff);
                   if (ys ==INFLATED ||(ys =longMultiplyPowerTen(ys,raise)) ==INFLATED)
                       snd = augend.bigMultiplyPowerTen(raise);
               }
          }
          if (xs !=INFLATED && ys !=INFLATED) {
              long sum = xs + ys;
              if ( (((sum ^ xs) &(sum ^ ys))) >= 0L)//判断有无溢出
                 return BigDecimal.valueOf(sum,rscale);//返回使用BigDecimal的静态工厂方法得到的BigDecimal实例
           }
           if (fst ==null)
               fst =BigInteger.valueOf(xs);//BigInteger的静态工厂方法
           if (snd ==null)
               snd =BigInteger.valueOf(ys);
           BigInteger sum =fst.add(snd);
           return (fst.signum == snd.signum) ?new BigDecimal(sum,INFLATED, rscale, 0) :
              new BigDecimal(sum,compactValFor(sum),rscale, 0);//返回通过其他构造方法得到的BigDecimal对象
       }

使用BigDecimal原因:

在涉及到精确计算的时候,使用浮点型的数据很可能会出现你意想不到的结果。即使在使用BigDecimal的时候,也应该使用new BigDecimal(Stringvalue) 或 BigDecimal.valueof( double value)

猜你喜欢

转载自blog.csdn.net/a756556384/article/details/80323756