1. Introduction
1.导言
In our daily tasks, we may often come across challenges to format double values. One such challenge could be printing a double value, avoiding scientific notation. Even though this method helps us express large and small values more compactly, there are situations where the default scientific notation might not be the most practical choice. In such cases, alternative approaches may need to be considered for a more suitable representation.
在日常工作中,我们可能会经常遇到格式化双数值的难题。其中一个挑战就是在打印双数值时避免使用科学符号。尽管这种方法可以帮助我们更简洁地表达大数值和小数值,但在某些情况下,默认的科学符号可能不是最实用的选择。在这种情况下,可能需要考虑使用其他方法来获得更合适的表示。
In this tutorial, we’ll explore various methods to print a double value without scientific notation in Java.
在本教程中,我们将探讨在 Java 中打印不使用科学计数法的双数值的各种方法。
2. About Scientific Notation
2.关于科学记数法
Scientific notation consists of two components: a coefficient and an exponent. Typically, a decimal number between 1 and 10 is the coefficient, while the exponent indicates the power of 10 by which the system multiplies the coefficient.
科学符号由两部分组成:系数和指数。通常,1 到 10 之间的十进制数就是系数,而指数则表示系统乘以系数的 10 的幂次。
In Java, scientific notation is often represented using the “e” notation, where “e” stands for exponent:
在 Java 中,科学记数法通常使用 “e” 符号表示,其中 “e” 代表指数:
double largeNumber = 256450000d;
System.out.println("Large Number: " + largeNumber);
double smallNumber = 0.0000046d;
System.out.println("Small Number: " + smallNumber);
Running the code from above will output to the console two scientifically notated numbers:
运行上述代码后,控制台将输出两个用科学符号表示的数字:
Large Number: 2.5645E8
Small Number: 4.6E-6
The first number was represented as 2.5645 * 108, and the second one as 4.6 * 10-6 using the “e” notation. This compact writing can help us many times, but it can also mislead us. Due to this, in the following, we’ll see some methods to eliminate it.
第一个数字用“e”符号表示为 2.5645 * 108,第二个数字用“e”符号表示为 4.6 * 10-6。这种紧凑的写法在很多时候可以帮助我们,但也可能误导我们。因此,在下文中,我们将介绍一些消除它的方法。
3. Using the DecimalFormat Class
3. 使用 DecimalFormat 类
We can easily control how numeric values are shown using the DecimalFormat class. Also, it allows us to specify formatting patterns. We can define the desired decimal places and other formatting details to suit our application’s requirements:
我们可以使用 DecimalFormat 类轻松控制数值的显示方式。此外,它还允许我们指定格式化模式。我们可以定义所需的小数位数和其他格式化细节,以满足应用程序的要求:
DecimalFormat df = new DecimalFormat("#.###########");
double largeNumber = 256450000d;
System.out.println("Large Number: " + df.format(largeNumber));
double smallNumber = 0.0000046d;
System.out.println("Small Number: " + df.format(smallNumber));
We created a pattern that consists of a sequence of special characters, possibly combined with text. In our examples, we opted for the ‘#’ character, which displays a digit when one is provided and nothing otherwise. If we run the code from above, we will print the numbers on the console without scientific notation:
我们创建的模式由一串特殊字符组成,可能与文本结合在一起。在我们的示例中,我们选择了 “#”字符,如果提供了一个数字,它就会显示一个数字,否则什么也不会显示。如果我们运行上面的代码,就会在控制台上打印出数字,但不使用科学计数法:
Large Number: 256450000
Small Number: 0.0000046
We can see that even if we put only one character for the integer part, it will always be retained, regardless of whether the pattern is smaller than the actual number.
我们可以看到,即使我们只在整数部分输入一个字符,无论模式是否小于实际数字,它都会被保留下来。
4. Using printf() Method
4. 使用 printf() 方法 5.
The printf() method in the PrintStream class offers a dynamic and straightforward way to format output. It closely resembles the traditional C-style printf() function.
PrintStream 类中的printf()方法提供了一种动态、直接的输出格式化方法。 它与传统 C 风格的printf()函数非常相似。
We’ll use the %f specifier to shape the presentation of floating-point numbers assertively:
我们将使用%f指定符来明确显示浮点数:
double largeNumber = 256450000d;
System.out.printf("Large Number: %.7f", largeNumber);
System.out.println();
double smallNumber = 0.0000046d;
System.out.printf("Small Number: %.7f", smallNumber);
In this case, we’ll output:
在这种情况下,我们将输出
Large Number: 256450000.0000000
Small Number: 0.0000046
If the number has no decimals, it will fill the decimal places with zeros. Also, if we don’t specify the number of decimals, it will print, by default, six decimal places.
如果数字没有小数位,它将用 0 填满小数位。此外,如果不指定小数位数,默认情况下将打印小数点后六位。
If we print our small number without explicitly specifying the number of decimals:
如果我们在打印小数时没有明确指定小数位数:
System.out.printf("Small Number: %f", smallNumber);
Because the value has more decimals than specified in the format, the printf() method will round the value:
由于数值的小数位数多于格式中指定的小数位数,printf() 方法将对数值进行四舍五入:
Small Number: 0.000005
5. Using BigDecimal
5.使用 BigDecimal
BigDecimal is ideal when dealing with financial calculations, scientific computations, or any application where maintaining precision is crucial. Unlike primitive data types or double values, which can lead to precision loss due to the inherent limitations of binary floating-point representation, BigDecimal allows us to specify the exact precision we need.
BigDecimal 是处理金融计算、科学计算或任何对精度要求极高的应用时的理想选择。原始数据类型或双数值会因二进制浮点表示法的固有限制而导致精度损失,而 BigDecimal 则不同,它允许我们指定所需的精确度。
When working with BigDecimal, the concept of scientific notation is inherently different. The class itself allows us to work with arbitrary precision numbers without resorting to scientific notation, providing a straightforward solution to the challenges posed by default representations:
在使用 BigDecimal 时,科学记数法的概念本质上是不同的。该类本身允许我们在不使用科学记数法的情况下处理任意精度的数字,为默认表示法带来的挑战提供了直接的解决方案:
double largeNumber = 256450000d;
System.out.println("Large Number: " + BigDecimal.valueOf(largeNumber).toPlainString());
double smallNumber = 0.0000046d;
System.out.println("Small Number: " + BigDecimal.valueOf(smallNumber).toPlainString());
In this example, we employ the BigDecimal.valueOf() method to convert a double value with scientific notation into a BigDecimal. Subsequently, the toPlainString() function converts our complex object into a printable string, providing a precise and easily interpretable representation.
在本例中,我们使用 BigDecimal.valueOf() 方法将一个使用科学符号的双数值转换为 BigDecimal 。随后,toPlainString() 函数将我们的复杂对象转换为可打印的字符串,从而提供精确且易于解释的表示。
Besides eliminating scientific notation, BigDecimal provides features such as customizable rounding modes, which can be crucial in financial applications. The ability to precisely control the number of decimal places and handle extremely large or small numbers makes BigDecimal a go-to choice for developers prioritizing accuracy and precision in their Java applications.
除了取消科学符号外,BigDecimal 还提供了可定制的四舍五入模式等功能,这些功能在金融应用中至关重要。BigDecimal 能够精确控制小数位数和处理极大或极小的数字,这使得 BigDecimal 成为在 Java 应用程序中优先考虑准确性和精确度的开发人员的首选。
6. Using String.format()
6. 使用 String.format()
The String.format() method shapes a String using a format string and arguments.
String.format() 方法使用格式字符串和参数塑造 String 形状。
Both String.format() and printf() methods use the java.util.Formatter class and share the exact underlying mechanism for formatting, providing a convenient way to produce well-structured output. However, there are subtle differences in their application and usage.
String.format()和 printf() 方法都使用 java.util.Formatter 类,并且共享格式化的精确底层机制,从而为生成结构良好的输出提供了一种便捷的方法。
double largeNumber = 256450000d;
String formattedLargeNumber = String.format("%.7f", largeNumber);
System.out.println("Large Number: " + formattedLargeNumber);
double smallNumber = 0.0000046d;
String formattedSmallNumber = String.format("%.7f", smallNumber);
System.out.println("Small Number: " + formattedSmallNumber);
As can be seen in the example above, the String.format() method returns a formatted string rather than directly printing it to the console. We can store the formatted string in a variable, therefore making it easier for us to handle it further or use it in different contexts. Both methods share the same format specifiers, so the syntax for formatting remains consistent between them.
从上面的示例中可以看出,String.format() 方法返回的是格式化后的字符串,而不是直接打印到控制台。我们可以将格式化后的字符串存储在一个变量中,从而方便我们进一步处理它或在不同的上下文中使用它。这两种方法共享相同的格式说明符,因此它们之间的格式化语法保持一致。
7. Conclusion
7.结论
In this article, we saw multiple avenues for avoiding scientific notation when printing double values. Even more, we’ve seen many ways to format numbers, small or large, using different methods. We also played with format specifiers to ensure our desired level of detail.
在本文中,我们看到了打印双数值时避免使用科学记数法的多种途径。此外,我们还看到了使用不同方法格式化大小数字的多种方法。我们还使用了格式指定器,以确保我们所需的详细程度。
Ultimately, the choice between methods rests on personal preference and the specific needs of the task. As always, the complete source code for the examples is available over on GitHub.
最终,选择哪种方法取决于个人偏好和任务的具体需求。一如既往,示例的完整源代码可在 GitHub 上获取。