如何使用Java在没有科学记数法的情况下打印double值?

Des*_*ble 208 java double

我想在没有指数形式的Java中打印double值.

double dexp = 12345678;
System.out.println("dexp: "+dexp);
Run Code Online (Sandbox Code Playgroud)

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

我希望它像这样打印: 12345678

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

Eri*_*ski 221

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

该程序打印:

2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000
Run Code Online (Sandbox Code Playgroud)

哪些都是相同的价值.

Protip:如果你对为什么那些随机数字出现在双值的某个阈值之外感到困惑,这个视频解释了:computerphile为什么0.1+ 0.2相等0.30000000000001

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


NPE*_*NPE 108

你可以使用printf()%f:

double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);
Run Code Online (Sandbox Code Playgroud)

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

System.out.printf("dexp: %.0f\n", dexp);
Run Code Online (Sandbox Code Playgroud)

这使用文档中说明的格式说明符语言.

toString()原始代码中使用的默认格式在此处拼写出来.

  • 它排除了数字 (10认同)
  • `%.0f`将数字四舍五入.有没有办法只丢弃尾随的零? (4认同)

JBE*_*JBE 89

简而言之:

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

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
Run Code Online (Sandbox Code Playgroud)

说明:

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

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

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // Output: 0.000000210000
    
    Run Code Online (Sandbox Code Playgroud)
  • 通过使用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
    
    Run Code Online (Sandbox Code Playgroud)
  • 通过使用DecimalFormat,您是本地依赖的.在法语区域设置中,小数点分隔符是逗号,而不是点:

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

    使用ENGLISH语言环境可确保在程序运行的任何位置获得小数点分隔符.

为什么使用340 setMaximumFractionDigits呢?

两个原因:

  • setMaximumFractionDigits接受一个整数,但其实现的最大允许位数DecimalFormat.DOUBLE_FRACTION_DIGITS等于340
  • Double.MIN_VALUE = 4.9E-324 所以340位数字你肯定不会绕过你的双倍而失去精确度.

  • `new BigDecimal(0.00000021d).toPlainString()`输出`0.0000002100000000000000010850153241148685623329583904705941677093505859375`这不是你所期望的...... (4认同)
  • ``BigDecimal.valueOf(0.00000021d).toPlainString()`` 也可以工作(它使用 BigDecimal 的 String 构造函数,这就是原因) (2认同)

Obl*_*obl 27

你可以尝试一下DecimalFormat.使用此类,您可以非常灵活地解析数字.
您可以准确设置要使用的模式.
以你的情况为例:

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


Man*_*uel 16

我有另一个涉及BigDecimal的toPlainString()的解决方案,但这次使用的是字符串构造函数,这在javadoc中是推荐的:

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

它看起来像最短的形式:

return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();
Run Code Online (Sandbox Code Playgroud)

在Java 8之前,对于任何零值双打,这会产生"0.0",因此您需要添加:

if (myDouble.doubleValue() == 0)
    return "0";
Run Code Online (Sandbox Code Playgroud)

必须额外检查NaN和无限值.

所有这些考虑的最终结果:

public static String doubleToString(Double d) {
    if (d == null)
        return null;
    if (d.isNaN() || d.isInfinite())
        return d.toString();

    // Pre Java 8, a value of 0 would yield "0.0" below
    if (d.doubleValue() == 0)
        return "0";
    return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我已经阅读了无数的方案来将double值转换为String,这是最好的:简短,直接,可配置. (2认同)

Nat*_*teS 8

只要您的号码是一个整数,这将有效:

double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);
Run Code Online (Sandbox Code Playgroud)

如果double变量在小数点后具有精度,则会截断它.


Ram*_*shi 8

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() )
    }
Run Code Online (Sandbox Code Playgroud)


Jam*_*esC 5

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

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);
    }
Run Code Online (Sandbox Code Playgroud)

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

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