前两天做题,用了python,但是没考虑精度问题,一直有问题。直到我打印出中间变量,我才傻了眼。
这不是我第一次遇到精度的问题了。上一次蓝桥杯省赛用python,也是被精度问题坑死。 既然再次遇到,那么这次就要好好研究明白。
为什么会有精度损失
我们知道,计算机内十进制数会保存为二进制,小数点前的数保存起来是没问题的,等用来表示整数。
但是小数点后的数字,就开始出问题了。计算机使用等来保存小数。 相加起来,有没有发现不太对:这些有限的数字加起来,很难组成你想要的小数。
比如的二进制就是。
要保存一个数,计算机存储的位数是有限的,所以无法存储这个无限循环小数,那计算机在丢弃位数的过程中,就会产生精度损失。
我在Java、Python3和JS里尝试计算,并打印结果。结果是这样的形式:
0.30000000000000004。
python如何解决这个问题
物理层无法解决的问题,我们只能通过软件进行解决。
1、round函数进行四舍五入
我们可以看到,被丢弃的都是位于后面的位数。而越往后表示的数就越小,那我们就可以使用四舍五入解决掉这些似乎无关紧要的数字。
round(1.20003, 2)
输出结果就是。保留了2位小数。
2、使用Demical类
这个暂时不做研究
3、使用int()强制转换
强制转换函数可以直接将小数部分去掉。
Java如何解决这个问题
1、Math.round()函数进行四舍五入
和python不同,这个函数只接受一个参数,要么是float要么是double。 也就是说,不保留小数,但是会考虑四舍五入。
如果你想实现小数后保留几位的四舍五入,也是可以的。
double a = 1.234567;
// 要想保留两位小数,那就先乘以100,处理后再强制转换再除以100.
double b = (double)Math.round(a*100) / 100;
System.out.println(b); // 输出 1.23
2、使用BigDecimal类
这个类可以实现高精度计算。建议使用字符串进行初始化。
// 浮点数构造方式有两种
new BigDecimal(12.3); // 不推荐,无法控制初始化的精度!
new BigDecimal("12.3"); // 推荐使用字符串的方式
- 加法:
BigDecimal result1 = num1.add(num2); - 减法subtract()函数
- 乘法multiply()函数
- 除法divide()函数
- 绝对值abs()函数
3、(int)强制转换
和python一样,直接砍掉小数部分。