JAVA基础-绝对慎用的变量-double,float

JAVA基础-绝对慎用的变量-double,float

对于刚接触java的童鞋俩说,变量应该是最先了解的,因为要写好代码,最基础的加减乘除是必须要使用的,这些元素就像学英语的is am are一样,即使英语考试就得了20分,日久生情,也能深刻了解其中的含义,然而这些……你真的会用了吗?

数据类型介绍

java中常用的用于表示数据的类型,int,long,float,double换成人话就是,小一点的整数用int,大一点的用long,小(短)一点的小数用float,大(长)一点的小数用double,这是大部分初学者对这4个类型的理解,当然只要有表示数据的方法,接下来的加减乘除就可以链接运算符号直接计算了。这里对4个类型进行一个详细说明

  1. int ,4个字节,32位,存储范围-2147483648 (-2的31次方) ~ 2147483647 (2的31次方-1);
  2. long ,8个字节,64位,存储范围-9223372036854775808 (-2的63次方) ~ 9223372036854775807 (2的63次方-1);
  3. float ,4个字节,32位,存储范围1.4E-45 (2的-149次方) ~ 3.4028235E38 (2的128次方-1);
  4. double ,8个字节,64位,存储范围4.9E-324 (2的-1074次方) 1.7976931348623157E308 (2的1024次方-1);

应用场景

根据上面的说明,int适用于比较小一些的整数,比如我们常见的for循环,int i=0;i<=10;i++,long用于比较大的整数,比如对应数据库Bigint这种比较大比较长的ID,float和double意思差不多,就是对应长短的小数位,那么按照大多数人的想法,正常的加减乘除运算,我们有这4个变量,足够了。

表示原理

这么简单的问题,为啥还要讲原理呢,因为讲完原理以后,你就会深刻的理解到,原来只用这几个变量,对有多大的坑。在讲原理之前,先抛出一个问题。如何用10进制表示三分之一这个数………………
下面为了简单说明一下,我们用正数做一个说明,其实负数也简单,就是有专门表示符号的位数。

1、计算机存储—整数
我们知道,计算机他只认识0,1,那么假设我们要表示10进制的8,转换为2进制为1000,10进制的10,转为2进制为1010,其实很简单。总结下算法就是对2取模。
2、计算机存储—小数
小数对2取馍基本上就取不出来了,那么计算机采用的方法就是, 乘2,然后取整数部分,我们拿0.125举例,0.1252=0.25,取整数部分0,0.252=0.5,取整数部分0,0.5*2=1,取整数部分1,那么结果就是001。当然0.125这个数据比较规矩,我们再来一个不规矩的
0.9
0.9X2=1.8,取整1;
0.8X2=1.6,取整1;
0.6X2=1.2,取整1;
0.2X2=0.4,取整0;
0.4X2=0.8,取整0;
0.8X2=1.6,取整1;
0.6X2=1.2,取整1;从这里开始,应该产生规律了,下面将无限循环,这和10进制表示三分之一,是一个道理

总结

根据原理的部分演练,也就是说,即使你只是定义了一个double 0.9,那么这个0.9也只是无限接近于0.9,他并不是真正的0.9,那么话不多说,上代码:

		double a = 0.9d;
		double b = 0.9d;
		System.out.println(a);
		System.out.println(a==b);
		double c = 0.6d;
		double d = 0.3d;
		System.out.println(c+d);
		System.out.println(a==(c+d));

代码运行结果
0.9
true
0.8999999999999999
false

第一个结果为为0.9,我们感觉并不意外,a等于b 因为都是0.9我们感觉也并不意外,而c+d并没有产生我们预期的结果,而是0.899999999999999999,当然在输出这个结果后,a也就不可能等于c+d了,这根本原因就是在于,因为我们定义的数字,在计算机内部,是无法精确存储的,而我们仅仅是做了一个加单的0.3+0.6就已经出现了位数的变化,那么当我们小数位数更多的时候,这个偏差是不可原谅的。
正确做法,使用bigdecimal

		BigDecimal c1 = new BigDecimal("0.6");
		BigDecimal d1 = new BigDecimal("0.3");
		System.out.println(c1.add(d1).doubleValue() == a);

这个结果输出是true,是因为decimal尽可能的保留运算的精度,当然他付出的代价其实也是更大的。
最后给刚刚学习java的新童鞋一个建议,直接忘掉float,double吧,这俩参数在高精度计算的时候,精度丢失会极为严重,当然其实他存在的场景不光是java,例如Mysql,因为计算机存储原理都是一样的,所以也仍然是不推荐的。
不要觉得BigDecimal比较长,不好写。。。精度计算是离不开他的。。对于参加工作的有条件的项目组,甚至可以建议,禁用float,double

唔,其实里面就是一个工具类,加减乘除、保留两位小数。一共5个方法。。。emmmm.....为啥分这么高呢。因为宝宝想分想疯了。 附代码,有土豪就打赏打赏,没土豪的直接拿去使吧。 package cn.cisdom.base.utils; import java.math.BigDecimal; import java.text.DecimalFormat; public class Calculation { public static final DecimalFormat df = new DecimalFormat("######0.00"); /** * @methodName format2point * @desc 保留两位小数点 * @param value * @return java.lang.String * @author xm * @create 2018/6/7 12:03 **/ public static String format2point(Number value) { return df.format(value); } public static Double add(Number value1, Number value2) { BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1.add(b2).doubleValue(); } /** * 提供精确的减法运算。 * * @param value1 * 减数 * @param value2 * 被减数 * @return 两个参数的差 */ public static Double sub(Number value1, Number value2) { BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1.subtract(b2).doubleValue(); } /** * 提供精确的乘法运算。 * * @param value1 * 被乘数 * @param value2 * 乘数 * @return 两个参数的积 */ public static Double mul(Number value1, Number value2) { BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1.multiply(b2).doubleValue(); } /** * 提供精确的除法运算。 * * @param value1 * 除数 * @param value2 * 被除数 * @return 除数/被除数 */ public static Double div(Number value1, Number value2) { //MathContext mc = new MathContext(2, RoundingMode.HALF_DOWN);//精度为2,舍入模式为大于0.5进1,否则舍弃 BigDecimal b1 = new BigDecimal(Double.toString(value1.doubleValue())); BigDecimal b2 = new BigDecimal(Double.toString(value2.doubleValue())); return b1.divide(b2).doubleValue(); } public static void main(String[] args) { Double aDouble=Calculation.add(56.9, 1.67); System.out.println(aDouble); Double bDouble=Calculation.sub(99.2,aDouble); System.out.println(bDouble); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值