【问题标题】:How do I print a double value without scientific notation using Java?如何使用 Java 在没有科学计数法的情况下打印双精度值?
【发布时间】:2013-04-12 11:00:42
【问题描述】:

我想在 Java 中打印一个没有指数形式的双精度值。

double dexp = 12345678;
System.out.println("dexp: "+dexp);

它显示了这个 E 符号:1.2345678E7

我希望它像这样打印:12345678

防止这种情况的最佳方法是什么?

【问题讨论】:

    标签: java double


    【解决方案1】:

    我有另一个涉及 BigDecimal 的 toPlainString() 的解决方案,但这次使用 javadoc 中推荐的 String-constructor:

    此构造函数与 Float.toString 和 Double.toString 返回的值兼容。这通常是将 float 或 double 转换为 BigDecimal 的首选方法,因为它不会受到 BigDecimal(double) 构造函数的不可预测性的影响。

    它的最短形式如下:

    return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();
    

    必须额外检查 NaN 和无限值,因此完整形式如下所示:

    public static String doubleToString(Double d) {
        if (d == null)
            return null;
        if (d.isNaN() || d.isInfinite())
            return d.toString();
    
        return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
    }
    

    这也可以复制/粘贴以与 Float 很好地配合使用。

    对于 Java 7 及更低版本,这会导致任何零值双精度数为“0.0”,因此您需要添加:

    if (d.doubleValue() == 0)
        return "0";
    

    【讨论】:

    • 我已经阅读了无数将双精度值转换为字符串的方案,这是最好的:简短、直接、可配置。
    • 为什么是d.doubleValue() == 0 而不是d == 0
    • 因为它避免了自动拆箱,在这种情况下我更喜欢自动拆箱,但对此的看法当然可能不同。如果您使用的是 java 8(9 可能相同),则可以完全省略这两行。
    • 刚用java 9试过,这2行也可以在9上省略。
    【解决方案2】:

    使用String.format ("%.0f", number)

    %.0f 表示零小数

    String numSring = String.format ("%.0f", firstNumber);
    System.out.println(numString);
    

    【讨论】:

      【解决方案3】:

      您可以将printf()%f 一起使用:

      double dexp = 12345678;
      System.out.printf("dexp: %f\n", dexp);
      

      这将打印dexp: 12345678.000000。如果您不想要小数部分,请使用

      System.out.printf("dexp: %.0f\n", dexp);
      
      %.0f 中的

      0 表示小数部分中有 0 个位置,即没有小数部分。如果您想打印具有所需小数位数的小数部分,那么只需提供类似 %.8f 的数字而不是 0。默认情况下,小数部分最多打印 6 位小数。

      这使用documentation 中解释的格式说明符语言。

      原始代码中使用的默认toString() 格式拼写为here

      【讨论】:

      • 但它显示dexp: 12345681.000000这是错误的值。实际上之后我想在我的网页上显示它,它像这样显示1.2345678E7。无论如何我可以通过它存储它像12345678 这样的任何双重形式以及任何其他方式?
      • @despicable:您可能一直在查看旧的、不完整的答案版本。尝试重新加载页面。应该有一段关于%.0f.
      • @despicable 您可以将 dexp 存储为 int 以便您可以轻松地同时使用它
      • 数字四舍五入
      • %.0f 将数字四舍五入。有没有办法只丢弃尾随的零?
      【解决方案4】:

      这可能是一个切线....但是如果您需要将一个数值作为整数(太大而不能成为整数)放入序列化程序(JSON 等)中,那么您可能需要“BigInterger”

      例子:

      值是一个字符串 - 7515904334

      我们需要在 Json 消息中将其表示为数字:

      {
          "contact_phone":"800220-3333",
          "servicer_id":7515904334,
          "servicer_name":"SOME CORPORATION"
      }
      

      我们无法打印它,否则我们会得到这个:

      {
          "contact_phone":"800220-3333",
          "servicer_id":"7515904334",
          "servicer_name":"SOME CORPORATION"
      }
      

      像这样将值添加到节点会产生所需的结果:

      BigInteger.valueOf(Long.parseLong(value, 10))
      

      我不确定这是否真的是主题,但由于这个问题是我在搜索我的解决方案时最热门的问题,所以我想我会在这里分享以帮助其他人,撒谎我,他们搜索得很差。 :D

      【讨论】:

        【解决方案5】:

        对于由double 表示的整数值,您可以使用此代码,这比其他解决方案要快得多。

        public static String doubleToString(final double d) {
            // check for integer, also see https://stackoverflow.com/a/9898613/868941 and
            // https://github.com/google/guava/blob/master/guava/src/com/google/common/math/DoubleMath.java
            if (isMathematicalInteger(d)) {
                return Long.toString((long)d);
            } else {
                // or use any of the solutions provided by others, this is the best
                DecimalFormat df = 
                    new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
                df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
                return df.format(d);
            }
        }
        
        // Java 8+
        public static boolean isMathematicalInteger(final double d) {
            return StrictMath.rint(d) == d && Double.isFinite(d);
        }
        

        【讨论】:

          【解决方案6】:

          Java/Kotlin 编译器将任何大于 9999999(大于或等于 1000 万)的值转换为科学计数法,即。 Epsilon 表示法

          例如:12345678 转换为 1.2345678E7

          使用此代码避免自动转换为科学计数法:

          fun setTotalSalesValue(String total) {
                  var valueWithoutEpsilon = total.toBigDecimal()
                  /* Set the converted value to your android text view using setText() function */
                  salesTextView.setText( valueWithoutEpsilon.toPlainString() )
              }
          

          【讨论】:

            【解决方案7】:

            我的解决方案: String str = String.format("%.0f", yourDouble);

            【讨论】:

              【解决方案8】:

              Java 防止双精度中的 E 表示法:

              将双精度数转换为普通数的五种不同方法:

              import java.math.BigDecimal;
              import java.text.DecimalFormat;
              
              public class Runner {
                  public static void main(String[] args) {
                      double myvalue = 0.00000021d;
              
                      //Option 1 Print bare double.
                      System.out.println(myvalue);
              
                      //Option2, use decimalFormat.
                      DecimalFormat df = new DecimalFormat("#");
                      df.setMaximumFractionDigits(8);
                      System.out.println(df.format(myvalue));
              
                      //Option 3, use printf.
                      System.out.printf("%.9f", myvalue);
                      System.out.println();
              
                      //Option 4, convert toBigDecimal and ask for toPlainString().
                      System.out.print(new BigDecimal(myvalue).toPlainString());
                      System.out.println();
              
                      //Option 5, String.format 
                      System.out.println(String.format("%.12f", myvalue));
                  }
              }
              

              这个程序打印:

              2.1E-7
              .00000021
              0.000000210
              0.000000210000000000000001085015324114868562332958390470594167709350585
              0.000000210000
              

              都是相同的值。

              Protip:如果你对为什么这些随机数字出现在 double 值中超过某个阈值感到困惑,这个视频解释了:computerphile 为什么0.1+0.2 等于 0.30000000000001

              http://youtube.com/watch?v=PZRI1IfStY0

              【讨论】:

              • 它只是告诉我们如何打印双精度值。如果我想以 JSON 格式返回呢?
              【解决方案9】:

              我需要将一些 double 转换为货币值,发现大多数解决方案都可以,但不适合我。

              DecimalFormat 最终成为了我的选择,所以这就是我所做的:

                 public String foo(double value) //Got here 6.743240136E7 or something..
                  {
                      DecimalFormat formatter;
              
                      if(value - (int)value > 0.0)
                          formatter = new DecimalFormat("0.00"); // Here you can also deal with rounding if you wish..
                      else
                          formatter = new DecimalFormat("0");
              
                      return formatter.format(value);
                  }
              

              如您所见,如果数字是自然的,我会得到 - 比如说 - 20000000 而不是 2E7(等等) - 没有任何小数点。

              如果是十进制,我只能得到两位小数。

              【讨论】:

                【解决方案10】:

                当我将其用作 math.Eval() 函数的字符串输入时,我在生产代码中遇到了同样的问题,该函数接受像“x + 20 / 50”这样的字符串

                我看了数百篇文章......最后我选择了这个,因为速度。而且因为 Eval 函数最终会将其转换回自己的数字格式,并且 math.Eval() 不支持其他方法返回的尾随 E-07,而且任何超过 5 dp 的东西对我的应用程序来说都太多了.

                这现在用于拥有 1,000 多个用户的应用程序的生产代码...

                double value = 0.0002111d;
                String s = Double.toString(((int)(value * 100000.0d))/100000.0d); // Round to 5 dp
                
                s display as:  0.00021
                

                【讨论】:

                  【解决方案11】:

                  简而言之:

                  如果你想摆脱尾随零和语言环境问题,那么你应该使用:

                  double myValue = 0.00000021d;
                  
                  DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
                  df.setMaximumFractionDigits(340); // 340 = DecimalFormat.DOUBLE_FRACTION_DIGITS
                  
                  System.out.println(df.format(myValue)); // Output: 0.00000021
                  

                  说明:

                  为什么其他答案不适合我:

                  • Double.toString()System.out.printlnFloatingDecimal.toJavaFormatString 如果 double 小于 10^-3 或大于或等于 10^7,则使用科学计数法
                  • 通过使用%f,默认的小数精度为 6,否则您可以对其进行硬编码,但如果您的小数较少,则会导致添加额外的零。示例:

                    double myValue = 0.00000021d;
                    String.format("%.12f", myvalue); // Output: 0.000000210000
                    
                  • 通过使用setMaximumFractionDigits(0);%.0f,您可以删除任何小数精度,这对于整数/长整数是可以的,但对于双精度数则不行:

                    double myValue = 0.00000021d;
                    System.out.println(String.format("%.0f", myvalue)); // Output: 0
                    DecimalFormat df = new DecimalFormat("0");
                    System.out.println(df.format(myValue)); // Output: 0
                    
                  • 通过使用 DecimalFormat,您可以依赖本地。在法语语言环境中,小数点分隔符是逗号,而不是点:

                    double myValue = 0.00000021d;
                    DecimalFormat df = new DecimalFormat("0");
                    df.setMaximumFractionDigits(340);
                    System.out.println(df.format(myvalue)); // Output: 0,00000021
                    

                    使用英语语言环境可确保您获得小数点分隔符,无论您的程序将在何处运行。

                  为什么要使用 340 来表示 setMaximumFractionDigits

                  两个原因:

                  • setMaximumFractionDigits 接受整数,但其实现允许的最大位数为 DecimalFormat.DOUBLE_FRACTION_DIGITS,等于 340
                  • Double.MIN_VALUE = 4.9E-324 因此,如果使用 340 位数字,您肯定不会舍入双精度数并丢失精度。

                  【讨论】:

                  • 您对new BigDecimal(myvalue).toPlainString() 的看法是什么?从docs.oracle.com/javase/7/docs/api/java/math/… 的描述中可以看出,当给定不同类型的数字时,它的行为方式并不明显,但它确实消除了科学记数法。
                  • new BigDecimal(0.00000021d).toPlainString() 输出 0.0000002100000000000000010850153241148685623329583904705941677093505859375 这不是你所期望的......
                  • 知道如何在 scala 中使用您的答案吗?可能是适当进口的问题,但我是新来的。
                  • BigDecimal.valueOf(0.00000021d).toPlainString() 也可以工作(这就是它使用 BigDecimal 的 String 构造函数的原因)
                  • 这个答案不适用于浮动:24.728352f 变为 "24.728351593017578"
                  【解决方案12】:

                  我认为每个人都有正确的想法,但并不是所有的答案都直截了当。 我可以看到这是一段非常有用的代码。这是一个可行的方法:

                  System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));
                  

                  ".8" 是您设置要显示的小数位数的位置。

                  我正在使用 Eclipse,它没有问题。

                  希望这对您有所帮助。如有任何反馈,我将不胜感激!

                  【讨论】:

                    【解决方案13】:

                    以下代码检测提供的数字是否以科学计数法表示。如果是这样,则在正常显示中最多以“25”位数字表示。

                     static String convertFromScientificNotation(double number) {
                        // Check if in scientific notation
                        if (String.valueOf(number).toLowerCase().contains("e")) {
                            System.out.println("The scientific notation number'"
                                    + number
                                    + "' detected, it will be converted to normal representation with 25 maximum fraction digits.");
                            NumberFormat formatter = new DecimalFormat();
                            formatter.setMaximumFractionDigits(25);
                            return formatter.format(number);
                        } else
                            return String.valueOf(number);
                    }
                    

                    【讨论】:

                      【解决方案14】:

                      只要您的号码是整数,这将起作用:

                      double dnexp = 12345678;
                      System.out.println("dexp: " + (long)dexp);
                      

                      如果双精度变量在小数点后有精度,它将截断它。

                      【讨论】:

                        【解决方案15】:

                        您可以使用DecimalFormat 进行尝试。通过这个课程,您可以非常灵活地解析您的数字。
                        您可以准确设置您想要使用的模式。
                        以您为例:

                        double test = 12345678;
                        DecimalFormat df = new DecimalFormat("#");
                        df.setMaximumFractionDigits(0);
                        System.out.println(df.format(test)); //12345678
                        

                        【讨论】:

                          猜你喜欢
                          • 2019-02-28
                          • 2011-02-22
                          • 2012-11-30
                          • 1970-01-01
                          • 2011-02-26
                          • 1970-01-01
                          • 2010-11-11
                          相关资源
                          最近更新 更多