java中float和double为什么会转为科学记数法?
1、背景
在日常开发中有时会使用到float或double数据类型,然而在前端接收到数据时发现数据为科学记数法,此时不能满足业务显示直观的需求。为什么float和double会变成科学记数法格式呢?什么情况下会自动转换?
2、思考
带着上面的两个问题,我们一起撸撸源码吧。
(1) Float类对数据赋值和显示时会调用toString()方法:
public static String toString(float f) { return FloatingDecimal.toJavaFormatString(f); }
(2) 在FloatingDecimal类中调用toJavaFormatString()时,需要调用转换器:
public static String toJavaFormatString(float var0) { return getBinaryToASCIIConverter(var0).toJavaFormatString(); }
(3) 其中BinaryToASCIIConverter接口的toJavaFormatString()方法实现如下:
public String toJavaFormatString() { int var1 = this.getChars(this.buffer); return new String(this.buffer, 0, var1); }
(4) 在getChars()方法中,float和double完成了科学记数法的变形
if (this.decExponent > 0 && this.decExponent < 8) { var3 = Math.min(this.nDigits, this.decExponent); System.arraycopy(this.digits, this.firstDigitIndex, var1, var2, var3); var5 = var2 + var3; if (var3 < this.decExponent) { var3 = this.decExponent - var3; Arrays.fill(var1, var5, var5 + var3, 0); var5 += var3; var1[var5++] = .; var1[var5++] = 0; } else { var1[var5++] = .; if (var3 < this.nDigits) { int var4 = this.nDigits - var3; System.arraycopy(this.digits, this.firstDigitIndex + var3, var1, var5, var4); var5 += var4; } else { var1[var5++] = 0; } } } else if (this.decExponent <= 0 && this.decExponent > -3) { var5 = var2 + 1; var1[var2] = 0; var1[var5++] = .; if (this.decExponent != 0) { Arrays.fill(var1, var5, var5 - this.decExponent, 0); var5 -= this.decExponent; } System.arraycopy(this.digits, this.firstDigitIndex, var1, var5, this.nDigits); var5 += this.nDigits; } else { var5 = var2 + 1; var1[var2] = this.digits[this.firstDigitIndex]; var1[var5++] = .; if (this.nDigits > 1) { System.arraycopy(this.digits, this.firstDigitIndex + 1, var1, var5, this.nDigits - 1); var5 += this.nDigits - 1; } else { var1[var5++] = 0; } var1[var5++] = E; if (this.decExponent <= 0) { var1[var5++] = -; var3 = -this.decExponent + 1; } else { var3 = this.decExponent - 1; } if (var3 <= 9) { var1[var5++] = (char)(var3 + 48); } else if (var3 <= 99) { var1[var5++] = (char)(var3 / 10 + 48); var1[var5++] = (char)(var3 % 10 + 48); } else { var1[var5++] = (char)(var3 / 100 + 48); var3 %= 100; var1[var5++] = (char)(var3 / 10 + 48); var1[var5++] = (char)(var3 % 10 + 48); } }
在此部分代码中,分为三个大部分进行了转换:小数点前的位数大于0位但小于8位,数值为小于1且小数点紧跟的0小于3个,小数点前位数大于等于8位或纯小数的小数点后的0大于等于3。
简而言之,当数据为12345678或者0.0001222类型时,float或double数据会自动转换为科学记数法格式。
3、解决方法
(1) 数据采用BigDecimal格式
(2) NumberFormat
public static void main(String[] args) { double d = 123456789.128d; String s1 = big(d); String s2 = big2(d); System.out.println(d); System.out.println(s1); System.out.println(s2); } // 方法一:NumberFormat private static String big(double d) { NumberFormat nf = NumberFormat.getInstance(); // 是否以逗号隔开, 默认true以逗号隔开,如[123,456,789.128] nf.setGroupingUsed(false); // 结果未做任何处理 return nf.format(d); } //方法二: BigDecimal private static String big2(double d) { BigDecimal d1 = new BigDecimal(Double.toString(d)); BigDecimal d2 = new BigDecimal(Integer.toString(1)); // 四舍五入,保留2位小数 return d1.divide(d2,2,BigDecimal.ROUND_HALF_UP).toString(); }
下一篇:
excel导出百万数据轻松解决