赞
踩
在日常开发中有时会使用到float或double数据类型,然而在前端接收到数据时发现数据为科学记数法,此时不能满足业务显示直观的需求。为什么float和double会变成科学记数法格式呢?什么情况下会自动转换?
带着上面的两个问题,我们一起撸撸源码吧。
(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数据会自动转换为科学记数法格式。
(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();
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。