方法定义

// 计算单个值的反正切(主值)
public static double atan(double a)

// 计算两个坐标的反正切(全值域)
public static double atan2(double y, double x)

功能说明

方法 数学表达 返回值范围 特点
atan(a) tan⁻¹(a) [-π/2, π/2] 单参数,输出受限
atan2(y,x) tan⁻¹(y/x) [-π, π] 双参数,保留象限信息

核心差异

  1. 象限处理能力

    • atan(a):无法区分第二/第四象限(如输入 -1 都返回 -π/4)
    • atan2(y,x):根据坐标自动判断象限(如 (-1,-1) 返回 -3π/4)
  2. 零点处理

    • atan(0) 返回 0.0
    • atan2(0,0) 返回 0.0(但实际应避免此输入)
  3. 特殊值处理
    | 输入 | atan() | atan2() | |-----------------------|---------------|------------------------| | NaN | NaN | NaN | | ±0.0 | ±0.0 | 根据坐标符号确定 | | ±Infinity | ±π/2 | 根据坐标计算角度 |


示例代码

// atan() 基础用法
double a = Math.atan(1);       // π/4 ≈ 0.7854
double b = Math.atan(Double.POSITIVE_INFINITY); // π/2 ≈ 1.5708

// atan2() 象限演示
double q1 = Math.atan2(1, 1);   // 第一象限: π/4 ≈ 0.7854
double q2 = Math.atan2(1, -1);  // 第二象限: 3π/4 ≈ 2.3562
double q3 = Math.atan2(-1, -1); // 第三象限: -3π/4 ≈ -2.3562
double q4 = Math.atan2(-1, 1);  // 第四象限: -π/4 ≈ -0.7854

// 角度转换
double degrees = Math.toDegrees(Math.atan2(1, 1)); // 45°

使用技巧

  1. 坐标系转换

    // 笛卡尔坐标 → 极坐标
    double r = Math.sqrt(x*x + y*y);
    double theta = Math.atan2(y, x);
    
  2. 角度差计算

    // 计算两点间角度差
    double angleDiff = Math.atan2(Math.sin(θ1-θ2), Math.cos(θ1-θ2));
    
  3. 方向判断

    // 判断目标方位 (E, NE, N, NW...)
    double angle = Math.toDegrees(Math.atan2(dy, dx));
    String direction = getDirection(angle); // 自定义方向映射
    

常见错误

  1. 混淆参数顺序

    // 错误:参数顺序应为 (y, x)
    double error = Math.atan2(x, y);
    
  2. 错误处理零点

    // 危险:atan2(0,0) 返回0.0(数学上未定义)
    if (x == 0 && y == 0) throw new IllegalArgumentException();
    
  3. 忽略返回值范围

    // 错误假设:atan() 输出范围 [0, 2π]
    double angle = Math.atan(slope); // 实际范围 [-π/2, π/2]
    

注意事项

  1. 计算精度

    • 极端值(如 10²⁰)可能导致精度丢失
    • 使用 StrictMath 版本保证跨平台一致性
  2. 性能考量

    • atan2()atan() 慢约 30%(因额外象限计算)
    • 密集循环中可缓存结果或近似计算
  3. 角度缠绕

    • 处理 -π/π 边界时需归一化:
      double normalizeAngle(double angle) {
          return angle - 2*Math.PI * Math.floor((angle + Math.PI)/(2*Math.PI));
      }
      

最佳实践

  1. 优先选择 atan2()

    // 更安全的斜率计算
    double angle = Math.atan2(y2 - y1, x2 - x1);
    
  2. 防御性编程

    double safeAtan2(double y, double x) {
        if (Double.isNaN(y) || Double.isNaN(x)) return Double.NaN;
        if (x == 0 && y == 0) return 0.0; // 或抛出自定义异常
        return Math.atan2(y, x);
    }
    
  3. 近似优化(精度要求低时):

    // Pade 近似 (|x| < 1 时误差 < 0.005)
    double approxAtan(double x) {
        double x2 = x * x;
        return x*(0.999866 + x2*(-0.3302995 + x2*(0.180141 - x2*0.085133)));
    }
    

总结

维度 atan() atan2()
输入 单参数 (斜率) 双参数 (y,x 坐标)
输出范围 [-π/2, π/2] [-π, π]
象限识别 ❌ 无法识别 ✅ 自动识别
零点安全 ❌ 需额外检查 (0,0)
性能 较快 较慢(约+30%耗时)
推荐场景 已知斜率的主值计算 坐标系转换、方向判断

实践口诀

反正切分两兄弟,atan 简单 atan2 强;
单参输出半圆周,双参全域辨方向;
坐标转换选 atan2,性能关键用近似;
零点处理要警惕,象限信息保周全。

在图形计算、导航系统和物理仿真中优先使用 atan2() 保证方向正确性;在已知角度主值的数学计算中使用 atan() 更高效。始终检查边界条件以避免未定义行为。