double 关键字
概述
double
是Java中的基本数据类型,表示64位双精度IEEE 754浮点数,取值范围约为±1.8E308(15-17位有效数字),是浮点运算的默认类型。
语法格式
double variableName; // 声明double变量
double variableName = 3.14159; // 浮点字面量(默认为double)
double variableName = 2.5d; // 显式添加d后缀
基本特性
public class DoubleBasicsExample {
public static void main(String[] args) {
// 基本声明和初始化
double d1 = 3.141592653589793;
double d2 = -2.718281828;
double d3 = 0.0;
double d4 = 1.0d; // 显式double后缀
System.out.println("π ≈ " + d1);
System.out.println("e ≈ " + d2);
System.out.println("d3 = " + d3);
System.out.println("d4 = " + d4);
// 常量值
System.out.println("double最小正值: " + Double.MIN_VALUE);
System.out.println("double最大值: " + Double.MAX_VALUE);
System.out.println("double最小正常值: " + Double.MIN_NORMAL);
System.out.println("double精度位数: " + Double.SIZE);
// 特殊值
double positiveInfinity = Double.POSITIVE_INFINITY;
double negativeInfinity = Double.NEGATIVE_INFINITY;
double notANumber = Double.NaN;
System.out.println("正无穷: " + positiveInfinity);
System.out.println("负无穷: " + negativeInfinity);
System.out.println("非数字: " + notANumber);
// 科学计数法
double scientific1 = 1.23e10; // 1.23 × 10^10
double scientific2 = 5.67e-15; // 5.67 × 10^-15
System.out.println("科学计数法1.23e10: " + scientific1);
System.out.println("科学计数法5.67e-15: " + scientific2);
// 高精度示例
double precise = 1.23456789012345678901234567890;
System.out.println("double高精度: " + precise);
// 数学常量
System.out.println("Math.PI: " + Math.PI);
System.out.println("Math.E: " + Math.E);
}
}
类型转换
public class DoubleConversionExample {
public static void main(String[] args) {
// 自动类型转换(向上转换)
byte b = 100;
short s = 1000;
int i = 100000;
long l = 1000000000L;
float f = 3.14f;
double fromByte = b;
double fromShort = s;
double fromInt = i;
double fromLong = l;
double fromFloat = f;
System.out.println("byte到double: " + fromByte);
System.out.println("short到double: " + fromShort);
System.out.println("int到double: " + fromInt);
System.out.println("long到double: " + fromLong);
System.out.println("float到double: " + fromFloat);
// 强制类型转换(可能丢失精度或溢出)
double large = 1.7976931348623157e308;
double decimal = 3.99999;
// double转整数(截断小数部分)
int intFromDouble = (int) decimal;
long longFromDouble = (long) decimal;
System.out.println("double转int: " + decimal + " -> " + intFromDouble);
System.out.println("double转long: " + decimal + " -> " + longFromDouble);
// double转float(可能丢失精度)
double highPrecision = 1.23456789012345;
float floatFromDouble = (float) highPrecision;
System.out.println("高精度double: " + highPrecision);
System.out.println("转为float: " + floatFromDouble);
System.out.println("精度丢失: " + (highPrecision != floatFromDouble));
// 字符串转换
String str = "3.141592653589793";
double doubleFromString = Double.parseDouble(str);
System.out.println("字符串转double: " + doubleFromString);
// double转字符串
double value = Math.E;
String stringFromDouble = Double.toString(value);
System.out.println("double转字符串: " + stringFromDouble);
// 进制转换(通过包装类)
double hexValue = Double.parseDouble("1F", 16); // 不支持,会抛异常
// 正确方式:先转为long再转为double
// double hexValue = (double) Long.parseLong("1F", 16);
}
}
精密数学运算
public class DoubleMathExample {
public static void main(String[] args) {
// 基本算术运算
double a = 10.123456789;
double b = 3.987654321;
System.out.println("高精度运算:");
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("加法: " + (a + b));
System.out.println("减法: " + (a - b));
System.out.println("乘法: " + (a * b));
System.out.println("除法: " + (a / b));
System.out.println("求余: " + (a % b));
// 高级数学函数
double x = 2.5;
System.out.println("\n高级数学函数:");
System.out.println("x = " + x);
System.out.println("√x = " + Math.sqrt(x));
System.out.println("x² = " + Math.pow(x, 2));
System.out.println("x³ = " + Math.pow(x, 3));
System.out.println("e^x = " + Math.exp(x));
System.out.println("ln(x) = " + Math.log(x));
System.out.println("log₁₀(x) = " + Math.log10(x));
// 三角函数
double degrees = 60.0;
double radians = Math.toRadians(degrees);
System.out.println("\n三角函数 (" + degrees + "°):");
System.out.println("sin = " + Math.sin(radians));
System.out.println("cos = " + Math.cos(radians));
System.out.println("tan = " + Math.tan(radians));
System.out.println("asin = " + Math.toDegrees(Math.asin(Math.sin(radians))) + "°");
System.out.println("acos = " + Math.toDegrees(Math.acos(Math.cos(radians))) + "°");
System.out.println("atan = " + Math.toDegrees(Math.atan(Math.tan(radians))) + "°");
// 双曲函数
System.out.println("\n双曲函数:");
System.out.println("sinh(" + x + ") = " + Math.sinh(x));
System.out.println("cosh(" + x + ") = " + Math.cosh(x));
System.out.println("tanh(" + x + ") = " + Math.tanh(x));
// 舍入函数
double value = 3.7;
System.out.println("\n舍入函数 (" + value + "):");
System.out.println("ceil = " + Math.ceil(value)); // 向上取整
System.out.println("floor = " + Math.floor(value)); // 向下取整
System.out.println("round = " + Math.round(value)); // 四舍五入
System.out.println("rint = " + Math.rint(value)); // 就近取整
// 随机数
System.out.println("\n随机数:");
for (int i = 0; i < 5; i++) {
System.out.println("Math.random(): " + Math.random());
}
}
}
科学计算应用
import java.text.DecimalFormat;
import java.util.Arrays;
public class DoubleScientificExample {
// 统计计算
public static class Statistics {
public static double mean(double[] data) {
double sum = 0.0;
for (double value : data) {
sum += value;
}
return sum / data.length;
}
public static double variance(double[] data) {
double mean = mean(data);
double sumSquares = 0.0;
for (double value : data) {
double diff = value - mean;
sumSquares += diff * diff;
}
return sumSquares / (data.length - 1);
}
public static double standardDeviation(double[] data) {
return Math.sqrt(variance(data));
}
public static double median(double[] data) {
double[] sorted = data.clone();
Arrays.sort(sorted);
int n = sorted.length;
if (n % 2 == 0) {
return (sorted[n/2 - 1] + sorted[n/2]) / 2.0;
} else {
return sorted[n/2];
}
}
}
// 数值积分(梯形法则)
public static double trapezoidalRule(DoubleFunction function, double a, double b, int n) {
double h = (b - a) / n;
double sum = (function.apply(a) + function.apply(b)) / 2.0;
for (int i = 1; i < n; i++) {
double x = a + i * h;
sum += function.apply(x);
}
return sum * h;
}
// 函数接口
@FunctionalInterface
interface DoubleFunction {
double apply(double x);
}
// 牛顿法求平方根
public static double sqrt(double n, double precision) {
if (n < 0) return Double.NaN;
if (n == 0) return 0;
double x = n;
while (true) {
double nextX = (x + n / x) / 2.0;
if (Math.abs(x - nextX) < precision) {
return nextX;
}
x = nextX;
}
}
// 复数类
public static class Complex {
private final double real;
private final double imaginary;
public Complex(double real, double imaginary) {
this.real = real;
this.imaginary = imaginary;
}
public Complex add(Complex other) {
return new Complex(this.real + other.real, this.imaginary + other.imaginary);
}
public Complex multiply(Complex other) {
double newReal = this.real * other.real - this.imaginary * other.imaginary;
double newImaginary = this.real * other.imaginary + this.imaginary * other.real;
return new Complex(newReal, newImaginary);
}
public double magnitude() {
return Math.sqrt(real * real + imaginary * imaginary);
}
public double phase() {
return Math.atan2(imaginary, real);
}
@Override
public String toString() {
if (imaginary >= 0) {
return String.format("%.3f + %.3fi", real, imaginary);
} else {
return String.format("%.3f - %.3fi", real, -imaginary);
}
}
}
public static void main(String[] args) {
System.out.println("=== 统计计算 ===");
double[] data = {1.2, 2.3, 3.1, 4.8, 2.7, 3.9, 1.8, 2.5, 3.6, 4.2};
System.out.println("数据: " + Arrays.toString(data));
System.out.printf("平均值: %.3f%n", Statistics.mean(data));
System.out.printf("方差: %.3f%n", Statistics.variance(data));
System.out.printf("标准差: %.3f%n", Statistics.standardDeviation(data));
System.out.printf("中位数: %.3f%n", Statistics.median(data));
System.out.println("\n=== 数值积分 ===");
// 计算 ∫₀¹ x² dx = 1/3
double integral = trapezoidalRule(x -> x * x, 0.0, 1.0, 1000);
System.out.printf("∫₀¹ x² dx ≈ %.6f (理论值: %.6f)%n", integral, 1.0/3.0);
// 计算 ∫₀^π sin(x) dx = 2
double sinIntegral = trapezoidalRule(Math::sin, 0.0, Math.PI, 1000);
System.out.printf("∫₀^π sin(x) dx ≈ %.6f (理论值: 2.000000)%n", sinIntegral);
System.out.println("\n=== 牛顿法求平方根 ===");
double[] numbers = {4.0, 9.0, 2.0, 100.0};
for (double num : numbers) {
double mySqrt = sqrt(num, 1e-10);
double mathSqrt = Math.sqrt(num);
System.out.printf("√%.1f: 自实现=%.10f, Math.sqrt=%.10f%n",
num, mySqrt, mathSqrt);
}
System.out.println("\n=== 复数运算 ===");
Complex c1 = new Complex(3.0, 4.0);
Complex c2 = new Complex(1.0, -2.0);
System.out.println("c1 = " + c1);
System.out.println("c2 = " + c2);
System.out.println("c1 + c2 = " + c1.add(c2));
System.out.println("c1 * c2 = " + c1.multiply(c2));
System.out.printf("|c1| = %.3f%n", c1.magnitude());
System.out.printf("arg(c1) = %.3f radians%n", c1.phase());
}
}
金融和经济计算
import java.text.NumberFormat;
import java.util.Locale;
public class DoubleFinanceExample {
// 复利计算
public static double compoundInterest(double principal, double rate, int periods, double time) {
return principal * Math.pow(1 + rate / periods, periods * time);
}
// 现值计算
public static double presentValue(double futureValue, double rate, double time) {
return futureValue / Math.pow(1 + rate, time);
}
// 年金现值
public static double annuityPresentValue(double payment, double rate, int periods) {
if (rate == 0) return payment * periods;
return payment * (1 - Math.pow(1 + rate, -periods)) / rate;
}
// 贷款月供计算
public static double loanPayment(double principal, double monthlyRate, int months) {
if (monthlyRate == 0) return principal / months;
return principal * monthlyRate * Math.pow(1 + monthlyRate, months) /
(Math.pow(1 + monthlyRate, months) - 1);
}
// 内部收益率(IRR)近似计算
public static double approximateIRR(double[] cashFlows, double guess) {
double rate = guess;
double precision = 1e-6;
int maxIterations = 100;
for (int i = 0; i < maxIterations; i++) {
double npv = 0.0;
double dnpv = 0.0;
for (int j = 0; j < cashFlows.length; j++) {
double factor = Math.pow(1 + rate, j);
npv += cashFlows[j] / factor;
dnpv -= j * cashFlows[j] / (factor * (1 + rate));
}
if (Math.abs(npv) < precision) {
return rate;
}
rate = rate - npv / dnpv;
}
return Double.NaN; // 未收敛
}
// 波动率计算
public static double volatility(double[] returns) {
if (returns.length < 2) return 0.0;
double mean = 0.0;
for (double ret : returns) {
mean += ret;
}
mean /= returns.length;
double variance = 0.0;
for (double ret : returns) {
variance += Math.pow(ret - mean, 2);
}
variance /= returns.length - 1;
return Math.sqrt(variance * 252); // 年化波动率(假设252个交易日)
}
public static void main(String[] args) {
NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CHINA);
NumberFormat percent = NumberFormat.getPercentInstance();
percent.setMaximumFractionDigits(2);
System.out.println("=== 复利计算 ===");
double principal = 100000.0; // 本金10万
double annualRate = 0.06; // 年利率6%
double time = 10.0; // 10年
double futureValue = compoundInterest(principal, annualRate, 1, time);
System.out.println("本金: " + currency.format(principal));
System.out.println("年利率: " + percent.format(annualRate));
System.out.println("时间: " + time + " 年");
System.out.println("复利终值: " + currency.format(futureValue));
System.out.println("\n=== 现值计算 ===");
double pv = presentValue(futureValue, annualRate, time);
System.out.println("未来值: " + currency.format(futureValue));
System.out.println("现值: " + currency.format(pv));
System.out.println("\n=== 贷款计算 ===");
double loanAmount = 1000000.0; // 贷款100万
double monthlyRate = 0.05 / 12; // 月利率
int months = 30 * 12; // 30年
double monthlyPayment = loanPayment(loanAmount, monthlyRate, months);
double totalPayment = monthlyPayment * months;
double totalInterest = totalPayment - loanAmount;
System.out.println("贷款金额: " + currency.format(loanAmount));
System.out.println("年利率: " + percent.format(0.05));
System.out.println("贷款期限: " + (months/12) + " 年");
System.out.println("月供: " + currency.format(monthlyPayment));
System.out.println("总还款: " + currency.format(totalPayment));
System.out.println("总利息: " + currency.format(totalInterest));
System.out.println("\n=== 投资分析 ===");
// 年金现值计算
double annualPayment = 50000.0; // 年金5万
double discountRate = 0.08; // 折现率8%
int years = 20; // 20年
double annuityPV = annuityPresentValue(annualPayment, discountRate, years);
System.out.println("年金: " + currency.format(annualPayment));
System.out.println("折现率: " + percent.format(discountRate));
System.out.println("期限: " + years + " 年");
System.out.println("年金现值: " + currency.format(annuityPV));
System.out.println("\n=== IRR计算 ===");
double[] cashFlows = {-100000, 20000, 30000, 40000, 50000, 60000}; // 投资现金流
double irr = approximateIRR(cashFlows, 0.1);
System.out.println("现金流: " + java.util.Arrays.toString(cashFlows));
if (!Double.isNaN(irr)) {
System.out.println("内部收益率(IRR): " + percent.format(irr));
} else {
System.out.println("IRR计算未收敛");
}
System.out.println("\n=== 风险计算 ===");
double[] stockReturns = {0.12, -0.05, 0.18, 0.03, -0.08, 0.15, 0.02, -0.03, 0.09, 0.07};
double vol = volatility(stockReturns);
System.out.println("股票收益率: " + java.util.Arrays.toString(stockReturns));
System.out.println("年化波动率: " + percent.format(vol));
}
}
最佳实践
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
public class DoubleBestPractices {
// 1. 精确的浮点数比较
public static boolean doubleEquals(double a, double b, double epsilon) {
if (Double.isNaN(a) || Double.isNaN(b)) {
return Double.isNaN(a) && Double.isNaN(b);
}
if (Double.isInfinite(a) || Double.isInfinite(b)) {
return a == b;
}
return Math.abs(a - b) < epsilon;
}
public static boolean doubleEquals(double a, double b) {
return doubleEquals(a, b, 1e-9); // 默认精度
}
// 2. 相对误差比较(适用于大数值)
public static boolean doubleEqualsRelative(double a, double b, double relativeEpsilon) {
if (a == b) return true;
if (Double.isNaN(a) || Double.isNaN(b)) return false;
if (Double.isInfinite(a) || Double.isInfinite(b)) return false;
double larger = Math.max(Math.abs(a), Math.abs(b));
return Math.abs(a - b) < relativeEpsilon * larger;
}
// 3. 安全的数学运算
public static double safeDivide(double dividend, double divisor) {
if (divisor == 0.0) {
return dividend > 0 ? Double.POSITIVE_INFINITY :
dividend < 0 ? Double.NEGATIVE_INFINITY : Double.NaN;
}
return dividend / divisor;
}
public static double safeSqrt(double value) {
return value < 0 ? Double.NaN : Math.sqrt(value);
}
public static double safeLog(double value) {
return value <= 0 ? Double.NaN : Math.log(value);
}
// 4. 数值稳定的计算
public static double stableSum(double[] values) {
// Kahan求和算法,减少浮点累积误差
double sum = 0.0;
double compensation = 0.0;
for (double value : values) {
double adjustedValue = value - compensation;
double newSum = sum + adjustedValue;
compensation = (newSum - sum) - adjustedValue;
sum = newSum;
}
return sum;
}
// 5. 货币计算最佳实践
public static void monetaryCalculation() {
System.out.println("=== 货币计算比较 ===");
// 错误做法:直接使用double
double price1 = 0.1;
double price2 = 0.2;
double total1 = price1 + price2;
System.out.println("double计算: " + price1 + " + " + price2 + " = " + total1);
System.out.println("是否等于0.3: " + (total1 == 0.3));
// 正确做法:使用BigDecimal
BigDecimal bd1 = new BigDecimal("0.1");
BigDecimal bd2 = new BigDecimal("0.2");
BigDecimal total2 = bd1.add(bd2);
System.out.println("BigDecimal计算: " + bd1 + " + " + bd2 + " = " + total2);
System.out.println("是否等于0.3: " + total2.equals(new BigDecimal("0.3")));
// 如果必须使用double,整数化处理
long cents1 = Math.round(price1 * 100);
long cents2 = Math.round(price2 * 100);
long totalCents = cents1 + cents2;
double total3 = totalCents / 100.0;
System.out.println("整数化处理: " + total3);
}
// 6. 格式化输出
public static void formatDouble(double value) {
System.out.println("原始值: " + value);
// 使用DecimalFormat
DecimalFormat df1 = new DecimalFormat("#.##");
DecimalFormat df2 = new DecimalFormat("0.000");
DecimalFormat df3 = new DecimalFormat("#.##E0");
System.out.println("保留2位小数: " + df1.format(value));
System.out.println("固定3位小数: " + df2.format(value));
System.out.println("科学计数法: " + df3.format(value));
// 使用printf
System.out.printf("printf %.2f%n", value);
System.out.printf("printf %e%n", value);
System.out.printf("printf %g%n", value);
// 使用String.format
System.out.println("String.format: " + String.format("%.4f", value));
}
// 7. 边界值处理
public static boolean isValidNumber(double value) {
return Double.isFinite(value);
}
public static double clamp(double value, double min, double max) {
if (Double.isNaN(value)) return min;
return Math.max(min, Math.min(max, value));
}
// 8. 数组操作优化
public static double[] normalizeArray(double[] array) {
if (array == null || array.length == 0) {
return new double[0];
}
// 找到最大值
double max = Double.NEGATIVE_INFINITY;
for (double value : array) {
if (Double.isFinite(value) && value > max) {
max = value;
}
}
if (max == 0.0 || !Double.isFinite(max)) {
return array.clone();
}
// 归一化
double[] normalized = new double[array.length];
for (int i = 0; i < array.length; i++) {
normalized[i] = Double.isFinite(array[i]) ? array[i] / max : 0.0;
}
return normalized;
}
public static void main(String[] args) {
System.out.println("=== 浮点数比较 ===");
double a = 0.1 + 0.2;
double b = 0.3;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("直接比较 a == b: " + (a == b));
System.out.println("绝对误差比较: " + doubleEquals(a, b));
System.out.println("相对误差比较: " + doubleEqualsRelative(a, b, 1e-15));
System.out.println("\n=== 安全运算 ===");
System.out.println("safeDivide(1.0, 0.0): " + safeDivide(1.0, 0.0));
System.out.println("safeSqrt(-1.0): " + safeSqrt(-1.0));
System.out.println("safeLog(0.0): " + safeLog(0.0));
System.out.println("\n=== 数值稳定求和 ===");
double[] values = new double[1000000];
for (int i = 0; i < values.length; i++) {
values[i] = 0.1;
}
double simpleSum = 0.0;
for (double value : values) {
simpleSum += value;
}
double stableSum = stableSum(values);
double expected = values.length * 0.1;
System.out.println("期望值: " + expected);
System.out.println("简单求和: " + simpleSum);
System.out.println("稳定求和: " + stableSum);
System.out.println("简单求和误差: " + Math.abs(simpleSum - expected));
System.out.println("稳定求和误差: " + Math.abs(stableSum - expected));
monetaryCalculation();
System.out.println("\n=== 格式化输出 ===");
formatDouble(123.456789);
System.out.println("\n=== 数组归一化 ===");
double[] testArray = {1.0, 2.5, 3.7, 0.8, 4.2};
double[] normalized = normalizeArray(testArray);
System.out.println("原数组: " + java.util.Arrays.toString(testArray));
System.out.println("归一化: " + java.util.Arrays.toString(normalized));
}
}
double类型是Java中精度最高的内置数值类型,适用于科学计算、工程计算、统计分析等需要高精度的场景。在货币计算中建议使用BigDecimal以避免精度问题。