我想在 Java 中打印一个没有指数形式的双精度值。
double dexp = 12345678;
System.out.println("dexp: "+dexp);
它显示了这个 E 符号:1.2345678E7
。
我希望它像这样打印它:12345678
防止这种情况的最佳方法是什么?
将双精度数转换为普通数的五种不同方法:
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
?
您可以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()
格式在此处说明。
简而言之:
如果你想摆脱尾随零和区域设置问题,那么你应该使用:
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
orFloatingDecimal.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
等于 340Double.MIN_VALUE = 4.9E-324
因此,对于 340 位数字,您肯定不会舍入您的双精度数并丢失精度。你可以用DecimalFormat
. 通过这门课,您可以非常灵活地解析您的数字。
您可以准确设置您想要使用的模式。
以您为例:
double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
我有另一个涉及 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";
只要您的号码是整数,这将起作用:
double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);
如果 double 变量在小数点后有精度,它将截断它。
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() )
}
我需要将一些 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 (等等) - 没有任何小数点。
如果是十进制,我只能得到两位小数。
以下代码检测提供的数字是否以科学计数法表示。如果是这样,则在正常显示中最多以“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);
}
我认为每个人都有正确的想法,但所有的答案都不是直截了当的。我可以看到这是一段非常有用的代码。这是可行的代码片段:
System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));
这".8"
是您设置要显示的小数位数的地方。
我正在使用 Eclipse,它没有问题。
希望这会有所帮助。我将不胜感激任何反馈!
这可能是一个切线....但是如果您需要将一个数值作为整数(太大而不能成为整数)放入序列化程序(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
当我将其用作 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
利用String.format ("%.0f", number)
%.0f 表示零小数
String numSring = String.format ("%.0f", firstNumber);
System.out.println(numString);
对于由 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);
}
我的解决方案: String str = String.format ("%.0f", yourDouble);