⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/qq_30285985/ 「叁滴水」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

前言

电商项目开发时肯定少不了金额计算,金额计算时有很多让人坑人的地方,在此记录,以免被坑。

1、多精度计算问题

多精度不能直接计算,会存在经度缺失的问题。

public static void main (String[] args) {
double num1 = 1;
double num2 = 31.2;
double num3 = 323.03;
System.out.println (num1+num2+num3);
/**
* 355.22999999999996
*/
}

如上代码,3 个数值想加之后却得出了一个很长的数值。

在 java 开发中可以通过 BigDecimal 进行数值类型的计算,详细可到 BigDecimal 工具类。

数据库也是一样,mysql中有float和double类型,通过sql直接累加数据也会有精度缺失的情况。如果要精确的数值计算,要使用mysql的decimal类型。

2、包装类型比对

public static void main(String[] args) {
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2); // true
System.out.println(i3==i4); // false
}

如上代码很神奇,同样是数值比对100的时候可以通过双等号返回true。200就返回false。

这是因为Integer的valueOf()方法。

//Integer的valueOf方法
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

在[-128,128]之间的数,可以通过双等于比对成功,之外的数值就会返回一个new一个新的Integer,因此会返回false。Double的比较就简单一点,双等于比对全是false。这是因为Double直接是返回了一个新的Double。

//Double的valueOf方法
public static Double valueOf(String s) throws NumberFormatException {
return new Double(parseDouble(s));
}

在数值比对的时候乱的样子,那我发现他们都有eq方法,通过这个方法比对可以吗?

可以的,不管是Integer还是Double都存在一个equas方法,通过这个方法即可进行数值比对。但是这个方法不是很完美。

public static void main (String[] args){
Double i1 = 100d;
System.out.println(i1.equals ("100"));
//false
}

如上所示,因为太多的人都知道字符串类型不能用双等号进行比对,要用eq方法进行比对其value。

这样会让很多人误以为Integer和Double类型也是如此,而且在编码的时候如上这种写法也没有报错,会认为都是100肯定会返回true。恰巧这种想法是错误的。

public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}

Double的eq方法入参是Object类型,因此不管传入什么类型都不会报错。i1.equals ("100")这种就是双精度和字符进行比对,这两个永远都不可能返回true。正确的写法应该是i1.equals (100d)。

但是尽管多次提醒,但是还是会有不认真的开发小伙伴错误,因此,可以使用Double.compareTo方法,这个方法和eq方法类似,但是有编译的异常,这样可有效的提醒开发人员。

public static void main (String[] args){
Double i1 = 100d;
System.out.println(i1.compareTo (100d)); //0
System.out.println(i1.compareTo (1d)); //1
}

3、除以0会怎样?

小学的时候就讲过,进行除法运算时,除以0是没有意义的,开发过程中也是如此, 发现可能存在除以0的场景要特别注意,程序不会抛出异常,竟然会返回一个字符串!虽然这种场景不多,但是还是需要了解一下。

1除以0的场景:

public static void main(String[] args) {
Double d = 1d;
double v = d / 0d;
System.out.println(v);
//Infinity
}

0除以0的场景:

public static void main(String[] args) {
Double d = 0d;
double v = d / 0d;
System.out.println(v);
//NaN
}

4、float转double

public static void main(String[] args) {
Float f = 12312.12f;
System.out.println(f.doubleValue());
System.out.println(Double.parseDouble (f.toString ()));
//12312.1201171875
//12312.12
}

Float类中有一个doubleValue方法,返回值是一个double类型,这样会很容易的以为这是float转换double类型。但是转换之后精度缺失了,只能乖乖的换一种方式转换。

文章目录
  1. 1. 前言
  2. 2. 1、多精度计算问题
  3. 3. 2、包装类型比对
  4. 4. 3、除以0会怎样?
  5. 5. 4、float转double