android不在坑三:Float丢失精度
16lz
2021-01-25
android不在坑三:Float丢失精度
前言:
测试:你这个平均数,怎么一下正确一下错误,你让我怎么测啊!
面对测试的怒吼,赶快灰溜溜的检查代码去了。没错啊,最后测试for循环了几次才发现,日!怎么会这样,这不是坑么
后面开发商城的时候,基本全用String来,用BigDecimal进行精确运算
当然看看测试,float是怎么丢失精度的
public class Test_1 { public static void main(String[] args) { System.out.println(0.06+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println(303.1/1000); }}
运行结果如下。 0.06999999999999999 0.5800000000000001 401.49999999999994 0.30310000000000004
你认为你看错了,但结果却是是这样的。问题在哪里呢?原因在于我们的计算机是二进制的。浮点数没有办法是用二进制进行精确表示。我们的CPU表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。如:2.4的二进制表示并非就是精确的2.4。反而最为接近的二进制表示是 2.3999999999999999。浮点数的值实际上是由一个特定的数学公式计算得到的。
其实java的float只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。
好啦,送上大力丸工具类一枚。
public class DecimalUtil { /** * 金钱加法 */ public static String add(String v1, String v2) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.add(b2).toString(); } /** * 金钱乘法 */ public static String multiply(String v1, String v2) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.multiply(b2).toString(); } /** * 乘法 * * @param v1 乘数 * @param v2 被乘数 * @param scale 小数点保留位数 */ public static String multiplyWithScale(String v1, String v2, int scale) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); BigDecimal result = b1.multiply(b2); result = result.setScale(scale); return result.toString(); } /** * 金钱除法 */ public static String divide(String v1, String v2) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.divide(b2).toString(); } /** * 如果除不断,产生无限循环小数,那么就会抛出异常,解决方法就是对小数点后的位数做限制 * * @param v2 小数模式 ,DOWN,表示直接不做四舍五入,参考{@link RoundingMode} */ public static String divideWithRoundingDown(String v1, String v2) {return divideWithRoundingMode(v1, v2, RoundingMode.DOWN); } /** 选择小数部分处理方式 */ public static String divideWithRoundingMode(String v1, String v2, RoundingMode roundingMode) { return divideWithRoundingModeAndScale(v1, v2, RoundingMode.DOWN, 0); } /** * 选择小数点后部分处理方式,以及保留几位小数 * * @param v1 除数 * @param v2 被除数 * @param roundingMode 小数处理模式 * @param scale 保留几位 */ public static String divideWithRoundingModeAndScale(String v1, String v2, RoundingMode roundingMode, int scale) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.divide(b2, scale, roundingMode).toString(); } /** * 金钱减法 */ public static String subtract(String v1, String v2) { BigDecimal b1 = new BigDecimal(v1); BigDecimal b2 = new BigDecimal(v2); return b1.subtract(b2).toString(); }}
使用方法:
乘法:
String countIntegral = DecimalUtil.multiply(integral, num);
加法:
String selectedMoney = DecimalUtil.add(selectedMoney, countMoney);
结语:最后记得传入参数不能为空,即初始值要为0, String num="0",不然会报错
更多相关文章
- android的tone音源代码DTMF双音频何快速计算正弦波
- EditText保留两位小数并输入不超过最大值
- 基于Android的计算器(代码行数足够用来交大作业)
- Android(安卓)jni build 多个shared library
- android中editText保留小数点后两位
- Android使double保留两位小数的多方法 java保留两位小数
- 安卓简单计算器整理
- Android(安卓)画图 之 Matrix(一)
- Android实现EditText输入金额