【发布时间】:2013-04-12 11:00:42
【问题描述】:
我想在 Java 中打印一个没有指数形式的双精度值。
double dexp = 12345678;
System.out.println("dexp: "+dexp);
它显示了这个 E 符号:1.2345678E7。
我希望它像这样打印:12345678
防止这种情况的最佳方法是什么?
【问题讨论】:
我想在 Java 中打印一个没有指数形式的双精度值。
double dexp = 12345678;
System.out.println("dexp: "+dexp);
它显示了这个 E 符号:1.2345678E7。
我希望它像这样打印: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";
【讨论】:
d.doubleValue() == 0 而不是d == 0?
使用String.format ("%.0f", number)
%.0f 表示零小数
String numSring = String.format ("%.0f", firstNumber);
System.out.println(numString);
【讨论】:
您可以将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 位小数。
这使用documentation 中解释的格式说明符语言。
原始代码中使用的默认toString() 格式拼写为here。
【讨论】:
dexp: 12345681.000000这是错误的值。实际上之后我想在我的网页上显示它,它像这样显示1.2345678E7。无论如何我可以通过它存储它像12345678 这样的任何双重形式以及任何其他方式?
%.0f.
%.0f 将数字四舍五入。有没有办法只丢弃尾随的零?
这可能是一个切线....但是如果您需要将一个数值作为整数(太大而不能成为整数)放入序列化程序(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
【讨论】:
对于由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);
}
【讨论】:
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() )
}
【讨论】:
我的解决方案: String str = String.format("%.0f", yourDouble);
【讨论】:
将双精度数转换为普通数的五种不同方法:
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?
【讨论】:
我需要将一些 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(等等) - 没有任何小数点。
如果是十进制,我只能得到两位小数。
【讨论】:
当我将其用作 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
【讨论】:
简而言之:
如果你想摆脱尾随零和语言环境问题,那么你应该使用:
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_FRACTION_DIGITS,等于 340Double.MIN_VALUE = 4.9E-324 因此,如果使用 340 位数字,您肯定不会舍入双精度数并丢失精度。【讨论】:
new BigDecimal(myvalue).toPlainString() 的看法是什么?从docs.oracle.com/javase/7/docs/api/java/math/… 的描述中可以看出,当给定不同类型的数字时,它的行为方式并不明显,但它确实消除了科学记数法。
new BigDecimal(0.00000021d).toPlainString() 输出 0.0000002100000000000000010850153241148685623329583904705941677093505859375 这不是你所期望的......
BigDecimal.valueOf(0.00000021d).toPlainString() 也可以工作(这就是它使用 BigDecimal 的 String 构造函数的原因)
24.728352f 变为 "24.728351593017578"。
我认为每个人都有正确的想法,但并不是所有的答案都直截了当。 我可以看到这是一段非常有用的代码。这是一个可行的方法:
System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));
".8" 是您设置要显示的小数位数的位置。
我正在使用 Eclipse,它没有问题。
希望这对您有所帮助。如有任何反馈,我将不胜感激!
【讨论】:
以下代码检测提供的数字是否以科学计数法表示。如果是这样,则在正常显示中最多以“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);
}
【讨论】:
只要您的号码是整数,这将起作用:
double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);
如果双精度变量在小数点后有精度,它将截断它。
【讨论】:
您可以使用DecimalFormat 进行尝试。通过这个课程,您可以非常灵活地解析您的数字。
您可以准确设置您想要使用的模式。
以您为例:
double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678
【讨论】: