如何使用Java打印没有科学符号的双精度值?

如何使用Java打印没有科学符号的双精度值?,java,double,Java,Double,我想用Java打印一个没有指数形式的双值 double dexp = 12345678; System.out.println("dexp: "+dexp); 它显示了E符号:1.2345678E7 我希望它像这样打印:12345678 防止这种情况的最佳方法是什么?您可以使用printf()和%f: double dexp = 12345678; System.out.printf("dexp: %f\n", dexp); 这将打印dexp:12345678.00000

我想用Java打印一个没有指数形式的双值

double dexp = 12345678;
System.out.println("dexp: "+dexp);
它显示了E符号:
1.2345678E7

我希望它像这样打印:
12345678

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

您可以使用
printf()
%f

double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);
这将打印
dexp:12345678.000000
。如果不需要小数部分,请使用

System.out.printf("dexp: %.0f\n", dexp);
%中的0。0f
表示小数部分中的0个位置,即无小数部分。如果要打印小数位数为所需小数位数的小数部分,则只需提供如下数字,而不是0
%.8f
。默认情况下,小数部分最多打印6位小数

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


原始代码中使用的默认
toString()
格式已详细说明。

您可以使用
DecimalFormat
进行尝试。使用该类,您可以非常灵活地解析数字。
您可以精确设置要使用的图案。
以您的情况为例:

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

只要您的数字是一个整数,这将起作用:

double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);
如果双精度变量的精度在小数点之后,它将截断它。

Java防止双精度表示法: 将双精度数字转换为普通数字的五种不同方法:

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:如果您不明白为什么这些随机数字出现在双精度值中超过某个阈值,本视频将解释:computerphile为什么
0.1
+
0.2
等于
0.300000000000001


简而言之:

如果要消除尾随零和区域设置问题,则应使用:

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.println
    FloatingDecimal.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\u FRACTION\u digits
    ,等于340
  • Double.MIN_VALUE=4.9E-324
    因此,对于340位数字,您肯定不会舍入Double并失去精度

以下代码检测提供的数字是否以科学符号表示。如果是,则在正常演示文稿中以最多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);
}

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

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

这现在用于一个拥有1000多个用户的应用程序的生产代码中

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

s display as:  0.00021

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

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

它的最短形式如下所示:

return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();
在Java 8之前,对于任何零值双精度运算,结果都是“0.0”,因此您需要添加:

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很好地配合。

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


如果是十进制,我只能得到两个十进制数字。

我认为每个人都有正确的想法,但所有答案都不简单。 我认为这是一段非常有用的代码。以下是一段将起作用的内容:

System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));
“.8”
是设置要显示的小数位数的地方

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


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

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

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

Java/Kotlin编译器将任何大于999999(大于或等于1000万)的值转换为科学符号,即Epsilion符号

例如: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() )
    }
我的解决方案:
String str=String.format(“%.0f”,双精度)

这可能是一条切线。。。。但是如果你需要把一个数值作为i
{
    "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))
String numSring = String.format ("%.0f", firstNumber);
System.out.println(numString);