
文章插图
基本数据类型

文章插图

文章插图

文章插图

文章插图

文章插图

文章插图
浮点数存在误差浮点数有一个需要特别注意的点就是浮点数是有误差的,比如以下这段代码你觉得输出的什么结果:
public class Demo { public static void main(String[] args) {System.out.println(0.1+0.2 == 0.3);//输出false }}这段代码输出值是false,之所以是这个结果那是因为浮点数是存在误差的,也就yi是说0.1在计算机中存储时不是精确的0.1,而有可能是0.1000000001,或者其他数,而0.2或0.3也是如此,所以0.1+0.2和0.3在计算机中是不相等的 。因为浮点数存在这个特性,所以我们在编程中间要尽量避免用浮点数进行比较 。
如果非要用浮点数进行比较的话,那可以使用下面这个方法:
public class Demo { public static void main(String[] args) {float n = (float)1e-6;//表示10的-6次方System.out.println(0.1+0.2 - 0.3 < n);//输出true }}以上代码的输出值是true,该方法的原理是如果两个数相差足够小,小到可以忽略不记的话,这里的界限设置是10的-6次方,那证明比较的这两个数可以认为是相等的,此方法只能在所表示的浮点数的小数点后的位数不是很多的时候使用 。接下来我们再来看一种极端的情况,代码如下:
public class Demo { public static void main(String[] args) {System.out.println(0.30000000000000001 == 0.3);//输出true }}以上的代码输出true,但其实我们肉眼可以很直观的看出,这两个数虽然很接近,但他们绝对不相等,像这种极端的数我们是无法用上面的方法进行比较的,所以还是记住这句话:尽量避免对浮点数进行比较 。
文章插图

文章插图
BigDecimal类我们既然知道了浮点数是存在误差的,所以在数据本身需要准确精度存储时,我们是一定不会使用float和double的,比如金钱数额的存储 。这时我们通常使用
BigDecimal类进行存储,它是一个可以存储准确浮点数的类 。
文章插图
BigDecimal类的定义:
BigDecimal bd = new BigDecimal("123.456");BigDecimal使用scale()表示小数位数,例如:
BigDecimal d1 = new BigDecimal("987.65");BigDecimal d2 = new BigDecimal("987.6500");BigDecimal d3 = new BigDecimal("98765400");System.out.println(d1.scale()); // 2,表示两位小数System.out.println(d2.scale()); // 4System.out.println(d3.scale()); // 0BigDecimal中的stripTrailingZeros()方法,可以将BigDecimal格式化为去掉数值末尾0的相等的数:
BigDecimal d1 = new BigDecimal("123.4500");BigDecimal d2 = d1.stripTrailingZeros();System.out.println(d1+" "+d1.scale()); // 123.45004System.out.println(d2+" "+d2.scale()); // 123.452,因为去掉了00BigDecimal d3 = new BigDecimal("1234500");BigDecimal d4 = d3.stripTrailingZeros();System.out.println(d3+" "+d3.scale()); // 12345000System.out.println(d4+" "+d4.scale()); // 1.2345E+6-2BigDecimal的scale()返回负数,例如,-2,表示这个数是个整数,并且末尾有2个0 。以上的d4就是如此,去掉0后数值没变,只是换了一种表示方法 。BigDecimal可以设置它的scale,如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断:
import java.math.BigDecimal;import java.math.RoundingMode;public class Demo {public static void main(String[] args) {BigDecimal d1 = new BigDecimal("123.456789");BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); // 四舍五入,123.4568BigDecimal d3 = d1.setScale(4, RoundingMode.DOWN); // 直接截断,123.4567System.out.println(d2);//123.4568System.out.println(d3);//123.4567}}BigDecimal的加、减、乘、除:
import java.math.BigDecimal;public class Demo {public static void main(String[] args) {BigDecimal d1 = new BigDecimal("124.44");BigDecimal d2 = new BigDecimal("12.2");System.out.println(d1.add(d2));//d1+d2136.64System.out.println(d1.subtract(d2));//d1-d2112.24System.out.println(d1.multiply(d2));//d1*d21518.168System.out.println(d1.divide(d2));//d1/d210.2}}BigDecimal在做加、减、乘时,精度不会丢失,但是做除法时,存在无法除尽的情况,这时就必须指定精度以及如何进行截断:
import java.math.BigDecimal;import java.math.RoundingMode;public class Demo {public static void main(String[] args) {BigDecimal d1 = new BigDecimal("123.456");BigDecimal d2 = new BigDecimal("23.456789");BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP); // 保留10位小数并四舍五入BigDecimal d4 = d1.divide(d2); // 报错:ArithmeticException,因为除不尽}}- 可以对
BigDecimal做除法的同时求其余数:
import java.math.BigDecimal;public class Demo {public static void main(String[] args) {BigDecimal n = new BigDecimal("22.444");BigDecimal m = new BigDecimal("0.23");BigDecimal[] dr = n.divideAndRemainder(m);System.out.println(dr[0]); // 97.0System.out.println(dr[1]); // 0.134}}- 调用
divideAndRemainder()方法时,返回的数组包含两个BigDecimal,第一个是商,第二个是余数,商总是整数,余数不会大于余数,我们可以利用该方法判断两个BigDecimal是否是整数倍数:
BigDecimal n = new BigDecimal("12.34");BigDecimal m = new BigDecimal("0.12");BigDecimal[] dr = n.divideAndRemainder(m);if (dr[1].signum() == 0) {//signum()会基于此BigDecimal返回三个值-1、1、0,分别对应为该数小于0,大于0和等于0// n是m的整数倍}- 比较两个
BigDecimal的值是否相等时,要注意的是,使用equals()方法不但要求两个BigDecimal的值相等,还要求它们的scale()相等:
BigDecimal d1 = new BigDecimal("123.45");BigDecimal d2 = new BigDecimal("123.45000");System.out.println(d1.equals(d2)); // false,因为scale不同System.out.println(d1.equals(d2.stripTrailingZeros())); // true,因为d2去除尾部0后scale变为2,与d1相同注意:使用compareTo()来比较两个BigDecimal的值,不要用equals()- 使用
compareTo()方法来比较两数大小,它根据两个值的大小分别返回-1、1和0,分别表示小于、大于和等于 。
import java.math.BigDecimal;public class Demo {public static void main(String[] args) {BigDecimal d1 = new BigDecimal("123.45");BigDecimal d2 = new BigDecimal("123.45000");BigDecimal d3 = new BigDecimal("123.40");System.out.println(d1.compareTo(d2)); // 0System.out.println(d1.compareTo(d3));//1System.out.println(d3.compareTo(d2));// -1}}- 查看
BigDecimal的源码,可以发现一个BigDecimal是通过一个BigInteger和一个scale来表示的,即BigInteger表示一个完整的整数,而scale表示小数位数:
public class BigDecimal extends Number implements Comparable<BigDecimal> {private final BigInteger intVal;private final int scale;}
文章插图

文章插图

文章插图

文章插图

文章插图

文章插图
【java中浮点数取余运算 Java中浮点数的坑】更多精彩内容敬请关注微信公众号:【平兄聊Java】
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
