268

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

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

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

我希望它像这样打印它:12345678

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

4

15 回答 15

277

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

于 2014-01-05T18:53:32.257 回答
139

您可以printf()使用%f

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

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

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

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

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

原始代码中使用的默认toString()格式在此处说明。

于 2013-04-19T05:51:56.337 回答
123

简而言之:

如果你想摆脱尾随零和区域设置问题,那么你应该使用:

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.printlnorFloatingDecimal.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
    

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

为什么要使用 340setMaximumFractionDigits呢?

两个原因:

  • setMaximumFractionDigits接受一个整数,但其实现允许的最大位数DecimalFormat.DOUBLE_FRACTION_DIGITS等于 340
  • Double.MIN_VALUE = 4.9E-324因此,对于 340 位数字,您肯定不会舍入您的双精度数并丢失精度。
于 2014-08-14T12:21:23.997 回答
29

你可以用DecimalFormat. 通过这门课,您可以非常灵活地解析您的数字。
您可以准确设置您想要使用的模式。
以您为例:

double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
于 2013-04-19T06:08:54.063 回答
25

我有另一个涉及 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";
于 2016-08-10T12:39:06.917 回答
8

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

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

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

于 2013-08-09T14:37:39.287 回答
8

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

例如: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() )
    }
于 2018-02-08T05:51:02.593 回答
4

我需要将一些 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 (等等) - 没有任何小数点。

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

于 2016-12-22T14:39:31.983 回答
3

以下代码检测提供的数字是否以科学计数法表示。如果是这样,则在正常显示中最多以“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);
}
于 2015-06-07T23:48:07.943 回答
3

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

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

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

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

希望这会有所帮助。我将不胜感激任何反馈!

于 2017-03-08T00:39:11.590 回答
2

这可能是一个切线....但是如果您需要将一个数值作为整数(太大而不能成为整数)放入序列化程序(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

于 2020-02-21T11:58:23.660 回答
1

当我将其用作 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
于 2015-07-29T08:05:02.903 回答
0

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

%.0f 表示零小数

String numSring = String.format ("%.0f", firstNumber);
System.out.println(numString);
于 2021-01-17T22:44:56.730 回答
0

对于由 a 表示的整数值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);
}
于 2018-01-18T07:33:31.117 回答
-1

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

于 2019-02-14T08:46:28.793 回答