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

时间:2013-04-19 05:49:55

标签: java double

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

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

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

我希望它像这样打印:12345678

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

15 个答案:

答案 0 :(得分:215)

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

答案 1 :(得分:100)

您可以将printf()%f

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

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

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

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

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

答案 2 :(得分:82)

简而言之:

如果你想摆脱尾随零和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

<强>解释

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

  • 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
    

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

为什么使用340然后用于setMaximumFractionDigits

有两个原因:

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

答案 3 :(得分:26)

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

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

答案 4 :(得分:15)

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

  

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

它看起来像是最短的形式:

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

Pre Java 8,这导致&#34; 0.0&#34;对于任何零值双打,所以你需要添加:

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

必须额外检查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();
}

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

答案 5 :(得分:8)

只要您的号码是一个整数,这就可以使用:

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

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

答案 6 :(得分:4)

我需要将一些双倍转换为货币值,并发现大多数解决方案都没问题,但不适合我。

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(等等) - 没有任何小数点。

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

答案 7 :(得分:4)

Java / Kotlin编译器将任何大于9999999(大于或等于1000万)的值转换为科学计数法即ie。 Epsilion符号。

Ex:12345678转换为1.2345678E7

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

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

答案 8 :(得分:3)

以下代码检测所提供的数字是否以科学计数法表示。如果是这样,它在正常演示中表示,最多为&#39; 25&#39;位数。

 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);
}

答案 9 :(得分: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

答案 10 :(得分: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

答案 11 :(得分:1)

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

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

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

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

希望这有用。我将不胜感激任何反馈!

答案 12 :(得分:0)

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

SELECT SUM (
  CASE
    WHEN COALESCE (h1, h2, h3, h4, h5, h6, h7, h8) IS NOT NULL
    THEN 1
    ELSE 0
  END)
FROM yourtable;

答案 13 :(得分:0)

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

<块引用>

%.0f 表示零小数

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

答案 14 :(得分:-1)

我的解决方案: 字符串str = String.format(“%.0f”,yourDouble);