有效数字
左边第一个不是0的数字起,到精确到的位数止,所有的数字都叫做这个数的有效数字。
浮点型
float的范围为-2^128 ~ +2^128
double的范围为-2^1024 ~ +2^1024。
float:2^23 = 8388608,共七位,最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字。
double:2^52 = 4503599627370496,共16位,同理,double的精度为15~16位。
f是float,没有后缀默认是double
浮点数无法精确表示,bigdecimal不含任何误差
大数值:BigInterger,BigDecimal 运算符:add subtract multiply divide mod
整型
二进制:前缀为0b或0B。如0b101=5
八进制:前面加上一个0。八进制只有0~7八个数。如八进制的343,要写为0343
十进制:正常写
十六进制:前缀为0x或0X。如0x343=3*256+4*16+3=835
运算
除数和被除数为整数时,为整数除法
/做除,%取余
++a 先加1,后运算
a++ 先运算,后加1
位运算符:不短路
BigDecimal的加减乘除
下面为BigDecimal的用法:
序号 | 方 法 | 类型 | 描 述 |
1 | public BigDecimal(double val) | 构造 | 将double表示形式转换为BigDecimal |
2 | public BigDecimal(int val) | 构造 | 将int表示形式转换为BigDecimal |
3 | public BigDecimal(String val) | 构造 | 将字符串表示形式转换为BigDecimal |
4 | public BigDecimal add(BigDecimal augend) | 普通 | 加法 |
5 | public BigDecimal subtract(BigDecimal subtrahend) | 普通 | 减法 |
6 | public BigDecimal multiply(BigDecimal multiplicand) | 普通 | 乘法 |
7 | public BigDecimal divide(BigDecimal divisor) | 普通 | 除法 |
工具类
import java.math.BigDecimal;
public class Arith
{
//默认除法运算精度
private static final int DEF_DIV_SCALE = 10;
//构造器私有化,让这个类不能实例化
private Arith(){}
//提供精确的加法运算
public static double add(double v1, double v2)
{
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.add(b2).doubleValue();
}
//精确的减法运算
public static double sub(double v1, double v2)
{
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.subtract(b2).doubleValue();
}
//精确的乘法运算
public static double mul(double v1, double v2)
{
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.multiply(b2).doubleValue();
}
//提供(相对)精确的除法运算,当发生除不尽的情况时
//精确到小数点后10位的数字四舍五入
public static double div(double v1, double v2)
{
BigDecimal b1 = BigDecimal.valueOf(v1);
BigDecimal b2 = BigDecimal.valueOf(v2);
return b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static void main(String[] args)
{
System.out.println("0.05 + 0.01 = " + Arith.add(0.05, 0.01));
System.out.println("1.0 - 0.42 = " + Arith.sub(1.0, 0.42));
System.out.println("4.015*100 = " + Arith.mul(4.015, 100));
System.out.println("123.3/100 = " + Arith.div(123.3, 100));
}
}
Bigdecimal判断是否等于0
Bigdecimal b = new Bigdecimal("0")
// 返回true则等于0,返回false,则不等于0;
b.compareTo(BigDecimal.ZERO)==0
注:b.equals(BigDecimal.ZERO);
用equals方法和BigDecimal.ZERO进行比较。equals方法不仅仅比较值的大小是否相等,首先比较的是scale(scale是bigdecimal的保留小数点位数,比如 new Bigdecimal("1.001"),scale为3),也就是说,不但值得大小要相等,保留位数也要相等,equals才能返回true。
四舍五入
使用Math中四舍五入的方法
// 向上舍入,将数值向上舍入为最为接近的整数,返回值是double类型
Math.ceil(double a)
// 向下舍入,将数值向下舍入为最为接近的整数,返回值是double类型
Math.floor(double a)
// 标准舍入,将数值四舍五入为最为接近的整数,返回值是int类型
Math.round(float a)
// 标准舍入,将数值四舍五入为最为接近的整数,返回值是long类型
Math.round(double a)
Math.round()方式不建议使用,因为会有风险,如:
double d2 = Math.round(5.2654555*100)*0.01d;
System.out.println("d2:" + d2);
使用BigDecimal对象的方式
// 使用远离零方向舍入(ROUND_UP)方式四舍五入
double f0 = b0.setScale(3, BigDecimal.ROUND_UP).doubleValue();
// 使用趋向零方向舍入(ROUND_DOWN)方式四舍五入
double f1 = b1.setScale(3, BigDecimal.ROUND_DOWN).doubleValue();
// 使用向正无穷方向舍入(ROUND_CEILING)方式四舍五入
double f2 = b2.setScale(3, BigDecimal.ROUND_CEILING).doubleValue();
// 使用向负无穷方向舍入(ROUND_FLOOR)方式四舍五入
double f3 = b3.setScale(3, BigDecimal.ROUND_FLOOR).doubleValue();
// 使用最近数字舍入(5进)(ROUND_HALF_UP)方式四舍五入
double f4 = b4.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
// 使用最近数字舍入(5舍)(ROUND_HALF_DOWN)方式四舍五入
double f5 = b5.setScale(3, BigDecimal.ROUND_HALF_DOWN).doubleValue();
// 使用银行家舍入法(ROUND_HALF_EVEN)方式四舍五入
double f6 = b6.setScale(3, BigDecimal.ROUND_HALF_EVEN).doubleValue();
// 使用不需要舍入模式(ROUND_UNNECESSARY)方式四舍五入
double f7 = b7.setScale(4, BigDecimal.ROUND_UNNECESSARY).doubleValue();
(1).ROUND_UP:远离零方向舍入。
向绝对值最大的方向舍入,只要舍弃位非0即进位。
(2).ROUND_DOWN:趋向零方向舍入。
向绝对值最小的方向输入,所有的位都要舍弃,不存在进位情况。
(3).ROUND_CEILING:向正无穷方向舍入。
向正最大方向靠拢。若是正数,舍入行为类似于ROUND_UP,若为负数,舍入行为类似于ROUND_DOWN。Math.round()方法就是使用的此模式。
(4).ROUND_FLOOR:向负无穷方向舍入。
向负无穷方向靠拢。若是正数,舍入行为类似于ROUND_DOWN;若为负数,舍入行为类似于ROUND_UP。
(5).ROUND_HALF_UP:最近数字舍入(5进)。
这是我们最经典的四舍五入。
(6).ROUND_HALF_DOWN:最近数字舍入(5舍)。
在这里5是要舍弃的。
(7).ROUND_HALF_EVEN:银行家舍入法。
1).舍去位的数值小于5时,直接舍去。
2).舍去位的数值大于5时,进位后舍去。
3).当舍去位的数值等于5时,若5后面还有其他非0数值,则进位后舍去,若5后面是0时,则根据5前一位数的奇偶性来判断,奇数进位,偶数舍去。
(8).ROUND_UNNECESSARY:计算结果是精确的,不需要舍入模式。
使用DecimalFormat对象的方式
DecimalFormat默认采用了RoundingMode.HALF_EVEN这种类型,可以通过setRoundingMode方法进行设置四舍五入方式,而且format之后的结果是一个字符串类型String。
DecimalFormat df = new DecimalFormat("#.000");
//df.setRoundingMode(RoundingMode.DOWN);
System.out.println(df.format(new BigDecimal(10.2345)));//10.235
使用String.format方式
String.format可以格式化很多类型的数据,包括整数、浮点数、字符串、日期等
double d = 10.2345;
String result = String.format("%.3f", d);
System.out.println("result:" + result);
DecimalFormat
double number = 3.14159265359;
// 创建DecimalFormat对象,并设置保留两位小数的格式
DecimalFormat df = new DecimalFormat("#.##");
// 使用format方法进行四舍五入并保留两位小数
String result = df.format(number);
注:随机数
1、Math.random()产生[0,1)的随机数
2、Random.nextInt(n)表示生成[0,n)之间的随机数,不带参数是生成随机整数(正、负整数和0)
6位随机数验证码(Java生成6位随机数验证码_java 获取 6位随机数-CSDN博客)
public static int randomCode() {
return (int) ((Math.random() * 9 + 1) * 100000);
}
任意范围的随机数
// (start,end]
int num=(int) (Math.random()*(end-start+1)+start);
// [min, max]
int num = new Random().nextInt(max - min + 1) + min;
注:整数相除保留两位小数
int a=1099;
int b=93;
// 第一种
double f1 = new BigDecimal((float)a/b).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
// 第二种
DecimalFormat df = new DecimalFormat("0.00");//格式化小数
String num = df.format((float)a/b);//返回的是String类型
两个整型数据直接做除法运算,最终只能得到一个整数结果,小数部分被舍弃。
int a = 10;
int b = 3;
输出
a / b = 3
注:double 类型的运算跟实际结果有误差
如 :19.9-9.9=9.9999999999999,而不是10,百度后发现double相减会转换成二进制,因double有效位数为 16位这就会出现存储小数位数不够的情况,这种情况下就会出现误差。
解决方法就是使用BigDecimal,它的有效长度足够长可存储 小数位数因此可代替double来进行加减乘除
浮点数是不适合精确计算的,原因是计算机里面数的计算都是二进制计算的,我们其实输入的十进制数,有些十进制数转换成二进制是可以精确转换,而有些转换则不是精确转换,得到的是一个最靠近它的数,所以这里面就存在一个误差。另外,如果浮点数不进行计算时,在十进制里面浮点数能正确显示,如果浮点数参与了计算,那么浮点数二进制与十进制间的转换过程就会变得不可而知,变得不可逆。
注:long类型进行相加运算,值溢出的解决方法
用BigDecimal 封装下进行相加运算,返回时类型转换add.longValue()。
Long a = 2147483648L;
Long b = 2147483648L;
BigDecimal add = new BigDecimal(a).add(new BigDecimal(b));
System.out.println(add.longValue());