|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
1. Java中double类型简介
在Java中,double是64位双精度浮点数类型,是表示小数的主要数据类型之一。它可以表示的范围大约是±4.94065645841246544e-324到±1.79769313486231570e+308,精度为15-16位有效数字。在处理科学计算、金融数据或其他需要高精度小数的场景中,double类型被广泛使用。
- double pi = 3.141592653589793;
- double price = 19.99;
- double scientificNumber = 1.23e10; // 科学计数法表示12300000000.0
复制代码
2. 使用System.out.println输出double类型数据
2.1 基本输出
最简单的输出double类型数据的方法是使用System.out.println():
- public class BasicDoubleOutput {
- public static void main(String[] args) {
- double value = 3.141592653589793;
- System.out.println(value); // 输出: 3.141592653589793
-
- double price = 19.99;
- System.out.println(price); // 输出: 19.99
-
- double largeNumber = 123456789.987654321;
- System.out.println(largeNumber); // 输出: 1.2345678998765432E8
- }
- }
复制代码
2.2 与字符串拼接输出
可以将double类型数据与字符串拼接输出:
- public class StringConcatenation {
- public static void main(String[] args) {
- double pi = 3.14159;
- System.out.println("圆周率的值是: " + pi); // 输出: 圆周率的值是: 3.14159
-
- double price = 19.99;
- System.out.println("商品价格: $" + price); // 输出: 商品价格: $19.99
- }
- }
复制代码
2.3 输出多个double值
可以在一个println语句中输出多个double值:
- public class MultipleDoubles {
- public static void main(String[] args) {
- double length = 10.5;
- double width = 5.25;
- System.out.println("长度: " + length + ", 宽度: " + width);
- // 输出: 长度: 10.5, 宽度: 5.25
-
- // 计算面积并输出
- double area = length * width;
- System.out.println("面积: " + area); // 输出: 面积: 55.125
- }
- }
复制代码
3. 使用System.out.printf进行格式化输出
3.1 基本格式化输出
printf方法允许我们使用格式说明符来控制输出的格式:
- public class PrintfBasic {
- public static void main(String[] args) {
- double pi = 3.141592653589793;
-
- // %f 表示浮点数格式
- System.out.printf("圆周率: %f%n", pi); // 输出: 圆周率: 3.141593
-
- // 指定小数位数
- System.out.printf("圆周率(2位小数): %.2f%n", pi); // 输出: 圆周率(2位小数): 3.14
- System.out.printf("圆周率(4位小数): %.4f%n", pi); // 输出: 圆周率(4位小数): 3.1416
-
- // 指定最小宽度
- System.out.printf("圆周率(宽度10): %10.2f%n", pi); // 输出: 圆周率(宽度10): 3.14
- System.out.printf("圆周率(宽度10,左对齐): %-10.2f%n", pi); // 输出: 圆周率(宽度10,左对齐): 3.14
- }
- }
复制代码
3.2 高级格式化选项
- public class PrintfAdvanced {
- public static void main(String[] args) {
- double value = 123.456789;
-
- // 使用逗号分组
- System.out.printf("带分组: %,.2f%n", 1234567.89); // 输出: 带分组: 1,234,567.89
-
- // 科学计数法
- System.out.printf("科学计数法: %e%n", value); // 输出: 科学计数法: 1.234568e+02
- System.out.printf("科学计数法(2位小数): %.2e%n", value); // 输出: 科学计数法(2位小数): 1.23e+02
-
- // 十六进制浮点数
- System.out.printf("十六进制浮点数: %a%n", value); // 输出: 十六进制浮点数: 0x1.edd2f1a9fbe77p6
-
- // 正负号显示
- System.out.printf("带正号: %+f%n", value); // 输出: 带正号: +123.456789
- System.out.printf("带正号: %+f%n", -value); // 输出: 带正号: -123.456789
-
- // 括号表示负数
- System.out.printf("括号表示负数: %(f%n", value); // 输出: 括号表示负数: 123.456789
- System.out.printf("括号表示负数: %(f%n", -value); // 输出: 括号表示负数: (123.456789)
- }
- }
复制代码
3.3 多个值格式化
- public class PrintfMultiple {
- public static void main(String[] args) {
- double price = 19.99;
- double taxRate = 0.08;
- double tax = price * taxRate;
- double total = price + tax;
-
- System.out.printf("商品价格: $%.2f%n", price);
- System.out.printf("税率: %.1f%%%n", taxRate * 100);
- System.out.printf("税额: $%.2f%n", tax);
- System.out.printf("总价: $%.2f%n", total);
-
- // 一行输出多个值
- System.out.printf("价格: $%.2f, 税率: %.1f%%, 总价: $%.2f%n",
- price, taxRate * 100, total);
- }
- }
复制代码
4. 使用String.format()格式化double
String.format()方法与printf类似,但它返回一个格式化后的字符串,而不是直接输出:
- public class StringFormatExample {
- public static void main(String[] args) {
- double pi = 3.141592653589793;
-
- // 基本格式化
- String formatted = String.format("圆周率: %.2f", pi);
- System.out.println(formatted); // 输出: 圆周率: 3.14
-
- // 多个值格式化
- double price = 19.99;
- double discount = 0.15;
- double discountedPrice = price * (1 - discount);
-
- String receipt = String.format("原价: $%.2f, 折扣: %.0f%%, 折后价: $%.2f",
- price, discount * 100, discountedPrice);
- System.out.println(receipt); // 输出: 原价: $19.99, 折扣: 15%, 折后价: $16.99
-
- // 在日志或消息中使用
- String logMessage = String.format("[INFO] 计算完成, 结果: %.4f", Math.sqrt(2));
- System.out.println(logMessage); // 输出: [INFO] 计算完成, 结果: 1.4142
- }
- }
复制代码
5. 使用DecimalFormat类进行高级格式化
5.1 DecimalFormat基本用法
DecimalFormat是NumberFormat的具体子类,用于格式化十进制数字。它提供了丰富的格式化选项:
- import java.text.DecimalFormat;
- public class DecimalFormatBasic {
- public static void main(String[] args) {
- double value = 1234.56789;
-
- // 创建DecimalFormat实例
- DecimalFormat df = new DecimalFormat();
-
- // 应用默认格式
- System.out.println("默认格式: " + df.format(value)); // 输出: 默认格式: 1,234.568
-
- // 自定义格式 - 两位小数
- df = new DecimalFormat("0.00");
- System.out.println("两位小数: " + df.format(value)); // 输出: 两位小数: 1234.57
-
- // 自定义格式 - 三位小数
- df = new DecimalFormat("0.000");
- System.out.println("三位小数: " + df.format(value)); // 输出: 三位小数: 1234.568
-
- // 自定义格式 - 整数部分
- df = new DecimalFormat("#");
- System.out.println("整数部分: " + df.format(value)); // 输出: 整数部分: 1235
-
- // 自定义格式 - 千位分隔符
- df = new DecimalFormat("#,###");
- System.out.println("千位分隔符: " + df.format(value)); // 输出: 千位分隔符: 1,235
-
- // 自定义格式 - 千位分隔符和两位小数
- df = new DecimalFormat("#,##0.00");
- System.out.println("千位分隔符和两位小数: " + df.format(value)); // 输出: 千位分隔符和两位小数: 1,234.57
- }
- }
复制代码
5.2 DecimalFormat高级模式
- import java.text.DecimalFormat;
- public class DecimalFormatAdvanced {
- public static void main(String[] args) {
- double value = 1234.5;
-
- // 前缀和后缀
- DecimalFormat df = new DecimalFormat("$#,##0.00");
- System.out.println("货币格式: " + df.format(value)); // 输出: 货币格式: $1,234.50
-
- df = new DecimalFormat("0.00%");
- System.out.println("百分比格式: " + df.format(0.85)); // 输出: 百分比格式: 85.00%
-
- // 科学计数法
- df = new DecimalFormat("0.###E0");
- System.out.println("科学计数法: " + df.format(12345)); // 输出: 科学计数法: 1.235E4
-
- // 正数、负数和零的不同格式
- df = new DecimalFormat("$#,##0.00;($#,##0.00)");
- System.out.println("正数: " + df.format(1234.5)); // 输出: 正数: $1,234.50
- System.out.println("负数: " + df.format(-1234.5)); // 输出: 负数: ($1,234.50)
-
- // 分数表示
- df = new DecimalFormat("# #/#");
- System.out.println("分数表示: " + df.format(0.75)); // 输出: 分数表示: 3 3/4
- }
- }
复制代码
5.3 DecimalFormat的舍入模式
- import java.text.DecimalFormat;
- import java.math.RoundingMode;
- public class DecimalFormatRounding {
- public static void main(String[] args) {
- double value = 3.14159;
-
- // 创建DecimalFormat实例
- DecimalFormat df = new DecimalFormat("0.00");
-
- // 设置舍入模式
- df.setRoundingMode(RoundingMode.UP);
- System.out.println("向上舍入: " + df.format(value)); // 输出: 向上舍入: 3.15
-
- df.setRoundingMode(RoundingMode.DOWN);
- System.out.println("向下舍入: " + df.format(value)); // 输出: 向下舍入: 3.14
-
- df.setRoundingMode(RoundingMode.CEILING);
- System.out.println("向正无穷舍入: " + df.format(value)); // 输出: 向正无穷舍入: 3.15
-
- df.setRoundingMode(RoundingMode.FLOOR);
- System.out.println("向负无穷舍入: " + df.format(value)); // 输出: 向负无穷舍入: 3.14
-
- df.setRoundingMode(RoundingMode.HALF_UP);
- System.out.println("四舍五入: " + df.format(value)); // 输出: 四舍五入: 3.14
-
- df.setRoundingMode(RoundingMode.HALF_DOWN);
- System.out.println("五舍六入: " + df.format(value)); // 输出: 五舍六入: 3.14
-
- df.setRoundingMode(RoundingMode.HALF_EVEN);
- System.out.println("银行家舍入法: " + df.format(value)); // 输出: 银行家舍入法: 3.14
-
- // 测试2.5的舍入
- double testValue = 2.5;
- df.setRoundingMode(RoundingMode.HALF_UP);
- System.out.println("2.5四舍五入: " + df.format(testValue)); // 输出: 2.5四舍五入: 2.50
-
- df.setRoundingMode(RoundingMode.HALF_EVEN);
- System.out.println("2.5银行家舍入法: " + df.format(testValue)); // 输出: 2.5银行家舍入法: 2.50
- }
- }
复制代码
6. 使用NumberFormat进行本地化格式化
NumberFormat是一个抽象基类,用于格式化数字。它可以根据本地环境自动调整格式:
- import java.text.NumberFormat;
- import java.util.Locale;
- public class NumberFormatExample {
- public static void main(String[] args) {
- double value = 1234567.89;
-
- // 获取默认环境的NumberFormat实例
- NumberFormat nf = NumberFormat.getInstance();
- System.out.println("默认格式: " + nf.format(value));
-
- // 获取特定环境的NumberFormat实例
- NumberFormat usFormat = NumberFormat.getInstance(Locale.US);
- System.out.println("美国格式: " + usFormat.format(value));
-
- NumberFormat germanFormat = NumberFormat.getInstance(Locale.GERMANY);
- System.out.println("德国格式: " + germanFormat.format(value));
-
- NumberFormat frenchFormat = NumberFormat.getInstance(Locale.FRANCE);
- System.out.println("法国格式: " + frenchFormat.format(value));
-
- // 货币格式
- NumberFormat currencyUs = NumberFormat.getCurrencyInstance(Locale.US);
- System.out.println("美国货币: " + currencyUs.format(value));
-
- NumberFormat currencyChina = NumberFormat.getCurrencyInstance(Locale.CHINA);
- System.out.println("中国货币: " + currencyChina.format(value));
-
- NumberFormat currencyJapan = NumberFormat.getCurrencyInstance(Locale.JAPAN);
- System.out.println("日本货币: " + currencyJapan.format(value));
-
- // 百分比格式
- NumberFormat percentFormat = NumberFormat.getPercentInstance();
- System.out.println("百分比: " + percentFormat.format(0.85));
-
- // 设置小数位数
- nf.setMinimumFractionDigits(2);
- nf.setMaximumFractionDigits(4);
- System.out.println("自定义小数位数: " + nf.format(value));
- }
- }
复制代码
7. 处理特殊double值
Java中的double类型有一些特殊值,如正无穷大、负无穷大和NaN(非数字),需要特殊处理:
- public class SpecialDoubleValues {
- public static void main(String[] args) {
- // 正无穷大
- double positiveInfinity = Double.POSITIVE_INFINITY;
- System.out.println("正无穷大: " + positiveInfinity);
- System.out.printf("正无穷大(格式化): %.2f%n", positiveInfinity);
-
- // 负无穷大
- double negativeInfinity = Double.NEGATIVE_INFINITY;
- System.out.println("负无穷大: " + negativeInfinity);
- System.out.printf("负无穷大(格式化): %.2f%n", negativeInfinity);
-
- // NaN
- double nan = Double.NaN;
- System.out.println("NaN: " + nan);
- System.out.printf("NaN(格式化): %.2f%n", nan);
-
- // 使用DecimalFormat处理特殊值
- java.text.DecimalFormat df = new java.text.DecimalFormat("#.##");
- System.out.println("正无穷大(DecimalFormat): " + df.format(positiveInfinity));
- System.out.println("负无穷大(DecimalFormat): " + df.format(negativeInfinity));
- System.out.println("NaN(DecimalFormat): " + df.format(nan));
-
- // 检查特殊值
- double x = 0.0;
- double y = 0.0;
- double result = x / y;
-
- if (Double.isInfinite(result)) {
- System.out.println("结果是无穷大");
- }
-
- if (Double.isNaN(result)) {
- System.out.println("结果是NaN");
- }
- }
- }
复制代码
8. 实际应用场景和最佳实践
8.1 金融计算中的格式化
- import java.text.DecimalFormat;
- import java.text.NumberFormat;
- import java.util.Locale;
- public class FinancialFormatting {
- public static void main(String[] args) {
- // 货币格式化
- double amount = 1234567.8956;
-
- // 使用DecimalFormat
- DecimalFormat currencyFormat = new DecimalFormat("$#,##0.00");
- System.out.println("金额: " + currencyFormat.format(amount));
-
- // 使用NumberFormat进行本地化货币格式化
- NumberFormat usCurrency = NumberFormat.getCurrencyInstance(Locale.US);
- NumberFormat chinaCurrency = NumberFormat.getCurrencyInstance(Locale.CHINA);
- NumberFormat japanCurrency = NumberFormat.getCurrencyInstance(Locale.JAPAN);
-
- System.out.println("美国货币: " + usCurrency.format(amount));
- System.out.println("中国货币: " + chinaCurrency.format(amount));
- System.out.println("日本货币: " + japanCurrency.format(amount));
-
- // 利率计算和格式化
- double principal = 10000.00;
- double rate = 0.035; // 3.5%
- double interest = principal * rate;
-
- DecimalFormat percentFormat = new DecimalFormat("0.00%");
- DecimalFormat decimalFormat = new DecimalFormat("#,##0.00");
-
- System.out.println("本金: " + decimalFormat.format(principal));
- System.out.println("利率: " + percentFormat.format(rate));
- System.out.println("利息: " + decimalFormat.format(interest));
-
- // 股票价格格式化
- double stockPrice = 123.456;
- DecimalFormat stockFormat = new DecimalFormat("0.000");
- System.out.println("股票价格: " + stockFormat.format(stockPrice));
- }
- }
复制代码
8.2 科学计算中的格式化
- import java.text.DecimalFormat;
- public class ScientificFormatting {
- public static void main(String[] args) {
- // 科学计数法
- double avogadro = 6.02214076e23;
- double planck = 6.62607015e-34;
-
- // 使用printf
- System.out.printf("阿伏伽德罗常数: %.4e%n", avogadro);
- System.out.printf("普朗克常数: %.4e%n", planck);
-
- // 使用DecimalFormat
- DecimalFormat scientificFormat = new DecimalFormat("0.###E0");
- System.out.println("阿伏伽德罗常数: " + scientificFormat.format(avogadro));
- System.out.println("普朗克常数: " + scientificFormat.format(planck));
-
- // 工程计数法(指数是3的倍数)
- DecimalFormat engineeringFormat = new DecimalFormat("##0.####E0");
- System.out.println("工程计数法: " + engineeringFormat.format(12345)); // 12.345E3
-
- // 设置有效数字
- double value = 123.456789;
- DecimalFormat significantDigits = new DecimalFormat("@@@@");
- System.out.println("4位有效数字: " + significantDigits.format(value));
- }
- }
复制代码
8.3 数据报表中的格式化
- import java.text.DecimalFormat;
- import java.text.NumberFormat;
- public class ReportFormatting {
- public static void main(String[] args) {
- // 创建表头
- System.out.println("----------------------------------------");
- System.out.printf("%-15s %10s %10s%n", "产品", "单价", "销量");
- System.out.println("----------------------------------------");
-
- // 产品数据
- String[] products = {"笔记本电脑", "智能手机", "平板电脑", "智能手表"};
- double[] prices = {5999.99, 3299.50, 2199.00, 1299.75};
- int[] quantities = {120, 250, 80, 300};
-
- // 格式化输出
- NumberFormat currencyFormat = NumberFormat.getCurrencyInstance();
- DecimalFormat quantityFormat = new DecimalFormat("#,###");
-
- for (int i = 0; i < products.length; i++) {
- System.out.printf("%-15s %12s %10s%n",
- products[i],
- currencyFormat.format(prices[i]),
- quantityFormat.format(quantities[i]));
- }
-
- System.out.println("----------------------------------------");
-
- // 计算并显示总计
- double totalRevenue = 0;
- int totalQuantity = 0;
-
- for (int i = 0; i < prices.length; i++) {
- totalRevenue += prices[i] * quantities[i];
- totalQuantity += quantities[i];
- }
-
- System.out.printf("%-15s %12s %10s%n",
- "总计",
- currencyFormat.format(totalRevenue),
- quantityFormat.format(totalQuantity));
- System.out.println("----------------------------------------");
-
- // 显示百分比
- System.out.println("\n销量占比:");
- for (int i = 0; i < products.length; i++) {
- double percentage = (double) quantities[i] / totalQuantity * 100;
- System.out.printf("%-15s %10.1f%%%n", products[i], percentage);
- }
- }
- }
复制代码
8.4 性能考虑和最佳实践
- import java.text.DecimalFormat;
- public class PerformanceBestPractices {
- public static void main(String[] args) {
- // 1. 重用DecimalFormat实例
- DecimalFormat decimalFormat = new DecimalFormat("#,##0.00");
-
- double[] values = {1234.567, 9876.543, 5555.555, 7777.777};
-
- // 好的做法:重用格式化对象
- for (double value : values) {
- System.out.println("格式化值: " + decimalFormat.format(value));
- }
-
- // 2. 在循环中避免创建新的格式化对象
- long startTime = System.currentTimeMillis();
-
- // 不好的做法:在循环中创建新的格式化对象
- for (int i = 0; i < 100000; i++) {
- DecimalFormat df = new DecimalFormat("#,##0.00");
- df.format(1234.56);
- }
-
- long endTime = System.currentTimeMillis();
- System.out.println("循环中创建DecimalFormat耗时: " + (endTime - startTime) + "ms");
-
- // 好的做法:重用格式化对象
- startTime = System.currentTimeMillis();
- DecimalFormat reusableDf = new DecimalFormat("#,##0.00");
-
- for (int i = 0; i < 100000; i++) {
- reusableDf.format(1234.56);
- }
-
- endTime = System.currentTimeMillis();
- System.out.println("重用DecimalFormat耗时: " + (endTime - startTime) + "ms");
-
- // 3. 线程安全考虑
- // DecimalFormat不是线程安全的,在多线程环境中应该:
- // a) 每个线程创建自己的实例
- // b) 使用同步
- // c) 使用ThreadLocal
-
- // 4. 选择合适的格式化方法
- // 简单输出:使用System.out.println
- // 基本格式化:使用printf或String.format
- // 复杂格式化或本地化:使用DecimalFormat或NumberFormat
-
- // 5. 处理异常
- try {
- // 可能会抛出异常的格式化操作
- String invalidPattern = "#,##0.00#";
- DecimalFormat invalidDf = new DecimalFormat(invalidPattern);
- System.out.println("格式化结果: " + invalidDf.format(1234.56));
- } catch (IllegalArgumentException e) {
- System.err.println("格式化模式错误: " + e.getMessage());
- }
- }
- }
复制代码
9. 总结
在Java中输出double类型数据有多种方法,从简单的System.out.println到复杂的DecimalFormat格式化。选择哪种方法取决于具体需求:
1. 简单输出:使用System.out.println,适用于快速调试和简单输出。
2. 基本格式化:使用System.out.printf或String.format,适用于需要控制小数位数、宽度等基本格式化需求的场景。
3. 高级格式化:使用DecimalFormat,适用于需要复杂格式化模式、特定舍入行为或本地化需求的场景。
4. 本地化格式化:使用NumberFormat,适用于需要根据不同地区习惯格式化数字的场景。
在实际应用中,应根据性能要求、线程安全需求和格式化复杂度选择合适的方法。同时,注意处理特殊double值(如无穷大和NaN)以确保程序的健壮性。
通过掌握这些double类型数据的输出和格式化技术,你可以在各种应用场景中灵活地展示数值数据,提高程序的用户体验和可读性。 |
|