如何使用 Java 打印没有科学记数法的双精度值?

发布于 2025-01-13 07:02:27 字数 228 浏览 5 评论 0原文

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

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

它显示此 E 表示法:1.2345678E7

我希望它像这样打印: 12345678

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

I want to print a double value in Java without exponential form.

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

It shows this E notation: 1.2345678E7.

I want it to print it like this: 12345678

What is the best way to prevent this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

记忆消瘦 2025-01-20 07:02:27

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

都是相同的值。

专业提示:如果您对为什么这些随机数字在双精度值中出现超出特定阈值感到困惑,此视频将解释:computerphile Why does 0.1+0.2 equal 0.30000000000001?

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

Java prevent E notation in a double:

Five different ways to convert a double to a normal number:

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

This program prints:

2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000

Which are all the same value.

Protip: If you are confused as to why those random digits appear beyond a certain threshold in the double value, this video explains: computerphile why does 0.1+0.2 equal 0.30000000000001?

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

旧故 2025-01-20 07:02:27

您可以将 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 位小数。

这使用文档中解释的格式说明符语言< /a>.

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

You could use printf() with %f:

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

This will print dexp: 12345678.000000. If you don't want the fractional part, use

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

0 in %.0f means 0 places in fractional part i.e no fractional part. If you want to print fractional part with desired number of decimal places then instead of 0 just provide the number like this %.8f. By default fractional part is printed up to 6 decimal places.

This uses the format specifier language explained in the documentation.

The default toString() format used in your original code is spelled out here.

ζ澈沫 2025-01-20 07:02:27

简而言之:

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

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

解释:

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

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

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // 输出:0.000000210000
    
  • 通过使用 setMaximumFractionDigits(0);%.0f 您可以删除任何小数精度,这对于整数/长整数来说很好,但对于双精度数则不然:< /p>

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

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

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

为什么要使用 340 作为 setMaximumFractionDigits

有两个原因:

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

In short:

If you want to get rid of trailing zeros and Locale problems, then you should use:

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

Explanation:

Why other answers did not suit me:

  • Double.toString() or System.out.println or FloatingDecimal.toJavaFormatString uses scientific notations if double is less than 10^-3 or greater than or equal to 10^7
  • By using %f, the default decimal precision is 6, otherwise you can hardcode it, but it results in extra zeros added if you have fewer decimals. Example:

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // Output: 0.000000210000
    
  • By using setMaximumFractionDigits(0); or %.0f you remove any decimal precision, which is fine for integers/longs, but not for double:

    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
    
  • By using DecimalFormat, you are local dependent. In French locale, the decimal separator is a comma, not a point:

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

    Using the ENGLISH locale makes sure you get a point for decimal separator, wherever your program will run.

Why using 340 then for setMaximumFractionDigits?

Two reasons:

  • setMaximumFractionDigits accepts an integer, but its implementation has a maximum digits allowed of DecimalFormat.DOUBLE_FRACTION_DIGITS which equals 340
  • Double.MIN_VALUE = 4.9E-324 so with 340 digits you are sure not to round your double and lose precision.
究竟谁懂我的在乎 2025-01-20 07:02:27

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

此构造函数与 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";

I've got another solution involving BigDecimal's toPlainString(), but this time using the String-constructor, which is recommended in the javadoc:

this constructor is compatible with the values returned by Float.toString and Double.toString. This is generally the preferred way to convert a float or double into a BigDecimal, as it doesn't suffer from the unpredictability of the BigDecimal(double) constructor.

It looks like this in its shortest form:

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

NaN and infinite values have to be checked extra, so looks like this in its complete form:

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

This can also be copied/pasted to work nicely with Float.

For Java 7 and below, this results in "0.0" for any zero-valued Doubles, so you would need to add:

if (d.doubleValue() == 0)
    return "0";
贪恋 2025-01-20 07:02:27

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

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

You can try it with DecimalFormat. With this class you are very flexible in parsing your numbers.
You can exactly set the pattern you want to use.
In your case for example:

double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
似最初 2025-01-20 07:02:27

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

Java/Kotlin compiler converts any value greater than 9999999 (greater than or equal to 10 million) to scientific notation ie. Epsilion notation.

Ex: 12345678 is converted to 1.2345678E7

Use this code to avoid automatic conversion to scientific notation:

fun setTotalSalesValue(String total) {
        var valueWithoutEpsilon = total.toBigDecimal()
        /* Set the converted value to your android text view using setText() function */
        salesTextView.setText( valueWithoutEpsilon.toPlainString() )
    }
明月夜 2025-01-20 07:02:27

只要您的数字是整数,这就会起作用:

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

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

This will work as long as your number is a whole number:

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

If the double variable has precision after the decimal point it will truncate it.

时光与爱终年不遇 2025-01-20 07:02:27

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

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

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

I needed to convert some double to currency values and found that most of the solutions were OK, but not for me.

The DecimalFormat was eventually the way for me, so here is what I've done:

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

As you can see, if the number is natural I get - say - 20000000 instead of 2E7 (etc.) - without any decimal point.

And if it's decimal, I get only two decimal digits.

撕心裂肺的伤痛 2025-01-20 07:02:27

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

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

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

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

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

I think everyone had the right idea, but all answers were not straightforward.
I can see this being a very useful piece of code. Here is a snippet of what will work:

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

the ".8" is where you set the number of decimal places you would like to show.

I am using Eclipse and it worked no problem.

Hope this was helpful. I would appreciate any feedback!

小清晰的声音 2025-01-20 07:02:27

以下代码检测提供的数字是否以科学记数法表示。如果是这样,则以正常表示方式表示,最多为“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);
}

The following code detects if the provided number is presented in scientific notation. If so it is represented in normal presentation with a maximum of '25' digits.

 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);
}
茶底世界 2025-01-20 07:02:27

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

示例:

value是一个字符串 - 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

This may be a tangent.... but if you need to put a numerical value as an integer (that is too big to be an integer) into a serializer (JSON, etc.) then you probably want "BigInterger"

Example:

value is a string - 7515904334

We need to represent it as a numerical in a Json message:

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

We can't print it or we'll get this:

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

Adding the value to the node like this produces the desired outcome:

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

I'm not sure this is really on-topic, but since this question was my top hit when I searched for my solution, I thought I would share here for the benefit of others, lie me, who search poorly. :D

酒废 2025-01-20 07:02:27

这不仅适用于整数:

double dexp = 12345678.12345678;
BigDecimal bigDecimal = new BigDecimal(Double.toString(dexp));
System.out.println("dexp: "+ bigDecimal.toPlainString());

This will work not only for a whole numbers:

double dexp = 12345678.12345678;
BigDecimal bigDecimal = new BigDecimal(Double.toString(dexp));
System.out.println("dexp: "+ bigDecimal.toPlainString());
葬﹪忆之殇 2025-01-20 07:02:27

当我将它用作 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

I had this same problem in my production code when I was using it as a string input to a math.Eval() function which takes a string like "x + 20 / 50"

I looked at hundreds of articles... In the end I went with this because of the speed. And because the Eval function was going to convert it back into its own number format eventually and math.Eval() didn't support the trailing E-07 that other methods returned, and anything over 5 dp was too much detail for my application anyway.

This is now used in production code for an application that has 1,000+ users...

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

s display as:  0.00021
握住我的手 2025-01-20 07:02:27

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

%.0f 表示零小数

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

use String.format ("%.0f", number)

%.0f for zero decimal

String numSring = String.format ("%.0f", firstNumber);
System.out.println(numString);
别低头,皇冠会掉 2025-01-20 07:02:27

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

My solution:
String str = String.format ("%.0f", yourDouble);

内心激荡 2025-01-20 07:02:27

对于由 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);
}

For integer values represented by a double, you can use this code, which is much faster than the other solutions.

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);
}
小女人ら 2025-01-20 07:02:27

这对我有用。输出将是一个字符串。

String.format("%.12f", myvalue);

This works for me. The output will be a String.

String.format("%.12f", myvalue);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文