当前位置:   article > 正文

java中float和double为什么会转为科学记数法?_java float科学计数法

java float科学计数法

1、背景

       在日常开发中有时会使用到float或double数据类型,然而在前端接收到数据时发现数据为科学记数法,此时不能满足业务显示直观的需求。为什么float和double会变成科学记数法格式呢?什么情况下会自动转换?

2、思考

         带着上面的两个问题,我们一起撸撸源码吧。

(1) Float类对数据赋值和显示时会调用toString()方法:

  1. public static String toString(float f) {
  2. return FloatingDecimal.toJavaFormatString(f);
  3. }

(2) 在FloatingDecimal类中调用toJavaFormatString()时,需要调用转换器:

  1. public static String toJavaFormatString(float var0) {
  2. return getBinaryToASCIIConverter(var0).toJavaFormatString();
  3. }

(3) 其中BinaryToASCIIConverter接口的toJavaFormatString()方法实现如下:

  1. public String toJavaFormatString() {
  2. int var1 = this.getChars(this.buffer);
  3. return new String(this.buffer, 0, var1);
  4. }

(4) 在getChars()方法中,float和double完成了科学记数法的变形

  1. if (this.decExponent > 0 && this.decExponent < 8) {
  2. var3 = Math.min(this.nDigits, this.decExponent);
  3. System.arraycopy(this.digits, this.firstDigitIndex, var1, var2, var3);
  4. var5 = var2 + var3;
  5. if (var3 < this.decExponent) {
  6. var3 = this.decExponent - var3;
  7. Arrays.fill(var1, var5, var5 + var3, '0');
  8. var5 += var3;
  9. var1[var5++] = '.';
  10. var1[var5++] = '0';
  11. } else {
  12. var1[var5++] = '.';
  13. if (var3 < this.nDigits) {
  14. int var4 = this.nDigits - var3;
  15. System.arraycopy(this.digits, this.firstDigitIndex + var3, var1, var5, var4);
  16. var5 += var4;
  17. } else {
  18. var1[var5++] = '0';
  19. }
  20. }
  21. } else if (this.decExponent <= 0 && this.decExponent > -3) {
  22. var5 = var2 + 1;
  23. var1[var2] = '0';
  24. var1[var5++] = '.';
  25. if (this.decExponent != 0) {
  26. Arrays.fill(var1, var5, var5 - this.decExponent, '0');
  27. var5 -= this.decExponent;
  28. }
  29. System.arraycopy(this.digits, this.firstDigitIndex, var1, var5, this.nDigits);
  30. var5 += this.nDigits;
  31. } else {
  32. var5 = var2 + 1;
  33. var1[var2] = this.digits[this.firstDigitIndex];
  34. var1[var5++] = '.';
  35. if (this.nDigits > 1) {
  36. System.arraycopy(this.digits, this.firstDigitIndex + 1, var1, var5, this.nDigits - 1);
  37. var5 += this.nDigits - 1;
  38. } else {
  39. var1[var5++] = '0';
  40. }
  41. var1[var5++] = 'E';
  42. if (this.decExponent <= 0) {
  43. var1[var5++] = '-';
  44. var3 = -this.decExponent + 1;
  45. } else {
  46. var3 = this.decExponent - 1;
  47. }
  48. if (var3 <= 9) {
  49. var1[var5++] = (char)(var3 + 48);
  50. } else if (var3 <= 99) {
  51. var1[var5++] = (char)(var3 / 10 + 48);
  52. var1[var5++] = (char)(var3 % 10 + 48);
  53. } else {
  54. var1[var5++] = (char)(var3 / 100 + 48);
  55. var3 %= 100;
  56. var1[var5++] = (char)(var3 / 10 + 48);
  57. var1[var5++] = (char)(var3 % 10 + 48);
  58. }
  59. }

在此部分代码中,分为三个大部分进行了转换:小数点前的位数大于0位但小于8位,数值为小于1且小数点紧跟的0小于3个,小数点前位数大于等于8位或纯小数的小数点后的0大于等于3。

简而言之,当数据为12345678或者0.0001222类型时,float或double数据会自动转换为科学记数法格式。

3、解决方法

(1) 数据采用BigDecimal格式

(2) NumberFormat

  1. public static void main(String[] args) {
  2. double d = 123456789.128d;
  3. String s1 = big(d);
  4. String s2 = big2(d);
  5. System.out.println(d);
  6. System.out.println(s1);
  7. System.out.println(s2);
  8. }
  9. // 方法一:NumberFormat
  10. private static String big(double d) {
  11. NumberFormat nf = NumberFormat.getInstance();
  12. // 是否以逗号隔开, 默认true以逗号隔开,如[123,456,789.128]
  13. nf.setGroupingUsed(false);
  14. // 结果未做任何处理
  15. return nf.format(d);
  16. }
  17. //方法二: BigDecimal
  18. private static String big2(double d) {
  19. BigDecimal d1 = new BigDecimal(Double.toString(d));
  20. BigDecimal d2 = new BigDecimal(Integer.toString(1));
  21. // 四舍五入,保留2位小数
  22. return d1.divide(d2,2,BigDecimal.ROUND_HALF_UP).toString();
  23. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/688315
推荐阅读
相关标签
  

闽ICP备14008679号