PHP acos()函数

三角函数: acos() 函数用于计算反余弦值,返回以弧度表示的角,其余弦值等于指定数字。

acos() 函数返回一个数的反余弦值(arccosine)。参数必须在 -1 到 1 之间,返回值的范围是 0 到 π 弧度。

函数语法

acos(float $num): float

参数说明

参数 类型 描述 必需
$num float 要计算反余弦值的数字,必须在 -1 到 1 之间(包含端点)

返回值

返回参数 $num 的反余弦值,以弧度为单位。返回值范围是 0 到 π(0 到 3.1415926535898)。

使用示例

示例1:基本用法 - 计算反余弦值

计算不同数字的反余弦值:

<?php
// 计算反余弦值
echo "acos(1) = " . acos(1) . " 弧度\n";        // 0
echo "acos(0.5) = " . acos(0.5) . " 弧度\n";    // 约 1.0471975511966
echo "acos(0) = " . acos(0) . " 弧度\n";        // 约 1.5707963267949 (π/2)
echo "acos(-0.5) = " . acos(-0.5) . " 弧度\n";  // 约 2.0943951023932
echo "acos(-1) = " . acos(-1) . " 弧度\n";      // 约 3.1415926535898 (π)

// 特殊值
echo "acos(0.70710678118655) = " . acos(0.70710678118655) . " 弧度\n";  // 约 0.78539816339745 (π/4)
echo "acos(-0.70710678118655) = " . acos(-0.70710678118655) . " 弧度\n"; // 约 2.3561944901923 (3π/4)

// 转换弧度到角度
$radians = acos(0.5);
$degrees = rad2deg($radians);
echo "acos(0.5) = " . $radians . " 弧度 (" . $degrees . " 度)\n";
?>

示例2:角度与弧度转换

在角度和弧度之间进行转换:

<?php
// 创建一个角度计算类
class AngleCalculator {
    const PI = M_PI;

    // 计算角度(度)的反余弦
    public static function acosDeg($value) {
        if ($value < -1 || $value > 1) {
            throw new InvalidArgumentException("值必须在 -1 到 1 之间");
        }
        return rad2deg(acos($value));
    }

    // 计算余弦为指定值的角度(度)
    public static function angleFromCosine($cosine) {
        $radians = acos($cosine);
        return rad2deg($radians);
    }

    // 检查角度是否在有效范围内
    public static function isValidCosine($value) {
        return $value >= -1 && $value <= 1;
    }
}

// 使用示例
echo "常见余弦值对应的角度:\n";
$cosineValues = [1, 0.8660254, 0.7071068, 0.5, 0, -0.5, -0.7071068, -0.8660254, -1];

foreach ($cosineValues as $cos) {
    if (AngleCalculator::isValidCosine($cos)) {
        $angle = AngleCalculator::angleFromCosine($cos);
        echo "cos(θ) = " . round($cos, 4) . " → θ = " . round($angle, 2) . "°\n";
    }
}

echo "\n特殊角度:\n";
$specialAngles = [
    '0°'   => cos(deg2rad(0)),
    '30°'  => cos(deg2rad(30)),
    '45°'  => cos(deg2rad(45)),
    '60°'  => cos(deg2rad(60)),
    '90°'  => cos(deg2rad(90)),
    '120°' => cos(deg2rad(120)),
    '180°' => cos(deg2rad(180))
];

foreach ($specialAngles as $angle => $cosine) {
    $calculatedAngle = round(acos($cosine), 4);
    echo "cos(" . $angle . ") = " . round($cosine, 4) . " → acos(" . round($cosine, 4) . ") = " . $calculatedAngle . " 弧度\n";
}
?>

示例3:计算三角形角度

在几何中使用acos()计算三角形角度:

<?php
// 使用余弦定理计算三角形角度
function calculateTriangleAngle($a, $b, $c) {
    // 验证边长是否有效
    if ($a <= 0 || $b <= 0 || $c <= 0) {
        throw new InvalidArgumentException("边长必须为正数");
    }

    // 检查三角形不等式
    if ($a + $b <= $c || $a + $c <= $b || $b + $c <= $a) {
        throw new InvalidArgumentException("边长不满足三角形不等式");
    }

    // 使用余弦定理计算角A(对边为a)
    $cosA = ($b * $b + $c * $c - $a * $a) / (2 * $b * $c);

    // 确保余弦值在有效范围内
    $cosA = max(-1, min(1, $cosA));

    return [
        'radians' => acos($cosA),
        'degrees' => rad2deg(acos($cosA))
    ];
}

// 使用示例:已知三边求角度
try {
    $sideA = 3;
    $sideB = 4;
    $sideC = 5;

    $angleA = calculateTriangleAngle($sideA, $sideB, $sideC);
    $angleB = calculateTriangleAngle($sideB, $sideA, $sideC);
    $angleC = calculateTriangleAngle($sideC, $sideA, $sideB);

    echo "三角形边长: a = {$sideA}, b = {$sideB}, c = {$sideC}\n";
    echo "角A: " . round($angleA['degrees'], 2) . "° (" . round($angleA['radians'], 4) . " 弧度)\n";
    echo "角B: " . round($angleB['degrees'], 2) . "° (" . round($angleB['radians'], 4) . " 弧度)\n";
    echo "角C: " . round($angleC['degrees'], 2) . "° (" . round($angleC['radians'], 4) . " 弧度)\n";
    echo "角度总和: " . round($angleA['degrees'] + $angleB['degrees'] + $angleC['degrees'], 2) . "°\n";

    // 检查是否为直角三角形
    $isRightTriangle = abs(cos(deg2rad(90)) - cos($angleA['radians'])) < 0.001 ||
                      abs(cos(deg2rad(90)) - cos($angleB['radians'])) < 0.001 ||
                      abs(cos(deg2rad(90)) - cos($angleC['radians'])) < 0.001;

    echo "是否为直角三角形: " . ($isRightTriangle ? "是" : "否") . "\n";

} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

// 计算已知两边和夹角求第三边
function calculateThirdSide($a, $b, $angleDegrees) {
    $angleRadians = deg2rad($angleDegrees);
    $cSquared = $a * $a + $b * $b - 2 * $a * $b * cos($angleRadians);
    return sqrt($cSquared);
}

echo "\n已知两边和夹角求第三边:\n";
$a = 5;
$b = 7;
$angle = 60; // 60度
$c = calculateThirdSide($a, $b, $angle);
echo "边a = {$a}, 边b = {$b}, 夹角 = {$angle}°\n";
echo "第三边c = " . round($c, 4) . "\n";
?>

示例4:向量和几何计算

在向量计算中使用acos():

<?php
// 计算两个向量之间的夹角
function angleBetweenVectors($v1, $v2) {
    // 计算点积
    $dotProduct = 0;
    for ($i = 0; $i < count($v1); $i++) {
        $dotProduct += $v1[$i] * $v2[$i];
    }

    // 计算向量长度
    $length1 = sqrt(array_sum(array_map(function($x) { return $x * $x; }, $v1)));
    $length2 = sqrt(array_sum(array_map(function($x) { return $x * $x; }, $v2)));

    // 计算余弦值
    if ($length1 == 0 || $length2 == 0) {
        throw new InvalidArgumentException("向量长度不能为零");
    }

    $cosine = $dotProduct / ($length1 * $length2);

    // 确保在有效范围内
    $cosine = max(-1, min(1, $cosine));

    return [
        'cosine' => $cosine,
        'radians' => acos($cosine),
        'degrees' => rad2deg(acos($cosine))
    ];
}

// 二维向量示例
$vector1 = [3, 4];
$vector2 = [1, 0];

try {
    $angleInfo = angleBetweenVectors($vector1, $vector2);
    echo "向量1: [" . implode(', ', $vector1) . "]\n";
    echo "向量2: [" . implode(', ', $vector2) . "]\n";
    echo "余弦值: " . round($angleInfo['cosine'], 4) . "\n";
    echo "夹角: " . round($angleInfo['degrees'], 2) . "° (" . round($angleInfo['radians'], 4) . " 弧度)\n";
} catch (Exception $e) {
    echo "错误: " . $e->getMessage() . "\n";
}

// 计算三维向量的夹角
function angleBetween3DVectors($v1, $v2) {
    // 确保是三维向量
    if (count($v1) != 3 || count($v2) != 3) {
        throw new InvalidArgumentException("需要三维向量");
    }

    $dotProduct = $v1[0] * $v2[0] + $v1[1] * $v2[1] + $v1[2] * $v2[2];
    $length1 = sqrt($v1[0]*$v1[0] + $v1[1]*$v1[1] + $v1[2]*$v1[2]);
    $length2 = sqrt($v2[0]*$v2[0] + $v2[1]*$v2[1] + $v2[2]*$v2[2]);

    if ($length1 == 0 || $length2 == 0) {
        return 0; // 零向量与任何向量的夹角定义为0
    }

    $cosine = $dotProduct / ($length1 * $length2);
    $cosine = max(-1, min(1, $cosine)); // 避免浮点误差

    return rad2deg(acos($cosine));
}

// 三维向量示例
$v1_3d = [1, 2, 3];
$v2_3d = [4, -1, 2];
$angle3d = angleBetween3DVectors($v1_3d, $v2_3d);
echo "\n三维向量夹角:\n";
echo "向量1: [" . implode(', ', $v1_3d) . "]\n";
echo "向量2: [" . implode(', ', $v2_3d) . "]\n";
echo "夹角: " . round($angle3d, 2) . "°\n";
?>

示例5:错误处理和边界条件

处理acos()函数可能出现的错误和边界情况:

<?php
// 安全的acos函数,包含错误处理
function safeAcos($value) {
    // 处理边界情况
    if (!is_numeric($value)) {
        throw new InvalidArgumentException("参数必须是数字");
    }

    // 处理浮点精度误差
    $epsilon = 1e-15;

    if ($value > 1) {
        // 如果值大于1但非常接近1(由于浮点误差)
        if (abs($value - 1) < $epsilon) {
            return 0.0; // acos(1) = 0
        }
        throw new RangeException("acos() 参数必须在 -1 到 1 之间。输入值: {$value}");
    }

    if ($value < -1) {
        // 如果值小于-1但非常接近-1
        if (abs($value + 1) < $epsilon) {
            return M_PI; // acos(-1) = π
        }
        throw new RangeException("acos() 参数必须在 -1 到 1 之间。输入值: {$value}");
    }

    // 确保值在有效范围内
    $clampedValue = max(-1, min(1, $value));

    // 特殊情况的精确值
    if (abs($clampedValue - 1) < $epsilon) return 0.0;
    if (abs($clampedValue + 1) < $epsilon) return M_PI;
    if (abs($clampedValue) < $epsilon) return M_PI_2; // π/2

    return acos($clampedValue);
}

// 测试安全acos函数
$testValues = [1, 0.5, 0, -0.5, -1, 1.0000000001, -1.0000000001, 2, -2, "abc"];

foreach ($testValues as $value) {
    echo "尝试计算 acos(" . var_export($value, true) . "): ";

    try {
        if (is_string($value) && !is_numeric($value)) {
            throw new InvalidArgumentException("非数字参数");
        }

        $result = safeAcos($value);
        echo round($result, 6) . " 弧度";

        // 转换为角度
        $degrees = rad2deg($result);
        echo " (" . round($degrees, 2) . " 度)";

    } catch (Exception $e) {
        echo "错误: " . $e->getMessage();
    }

    echo "\n";
}

// NAN和INF处理
echo "\n特殊值处理:\n";
$specialValues = [NAN, INF, -INF, 0.0];

foreach ($specialValues as $value) {
    echo "acos(";

    if (is_nan($value)) {
        echo "NAN";
    } elseif (is_infinite($value)) {
        echo $value > 0 ? "INF" : "-INF";
    } else {
        echo $value;
    }

    echo ") = ";

    $result = @acos($value); // 使用@抑制警告

    if (is_nan($result)) {
        echo "NAN";
    } elseif (is_infinite($result)) {
        echo $result > 0 ? "INF" : "-INF";
    } else {
        echo round($result, 4);
    }

    echo "\n";
}
?>

数学原理

反余弦定义

对于任意实数 x ∈ [-1, 1],反余弦函数 y = acos(x) 定义为:

y ∈ [0, π] 使得 cos(y) = x

反余弦是余弦函数的反函数,限制在 [0, π] 区间内。

定义域: [-1, 1]

值域: [0, π] 弧度

重要性质
  • 单调性:在定义域内单调递减
  • 奇偶性:非奇非偶函数
  • 对称性:acos(-x) = π - acos(x)
  • 导数:d/dx acos(x) = -1/√(1-x²)
  • 积分:∫acos(x)dx = x·acos(x) - √(1-x²) + C

应用场景

场景 描述 公式/代码
三角形计算 已知三边求角度(余弦定理) acos(($b²+$c²-$a²)/(2*$b*$c))
向量夹角 计算两个向量之间的夹角 acos($dotProduct/($len1*$len2))
极坐标转换 从直角坐标转换为极坐标 atan2($y, $x)acos($x/√($x²+$y²))
信号处理 计算相位差 acos($realPart/$amplitude)
机器人学 计算关节角度 acos(($a²+$b²-$c²)/(2*$a*$b))

注意事项

重要提醒
  • 参数范围:参数必须在 -1 到 1 之间,超出范围会返回 NAN
  • 浮点精度:由于浮点数精度限制,接近 ±1 的值可能产生微小误差
  • 返回值单位:返回值以弧度为单位,不是角度
  • 特殊值:acos(NAN) 返回 NANacos(INF) 返回 NAN
  • 性能:acos() 是内置函数,性能较高,但大量计算时仍需优化

相关函数

cos()

计算余弦值

asin()

计算反正弦值

atan()

计算反正切值

atan2()

计算两个变量的反正切

deg2rad()

将角度转换为弧度

rad2deg()

将弧度转换为角度

常见问题

因为余弦函数的输出范围就是[-1, 1]。对于任何角度θ,cos(θ)的值都在这个范围内。acos()作为反函数,其输入(原函数的输出)自然也必须在这个范围内。超出这个范围的值没有对应的角度满足cos(θ)=x,因此acos()无法计算。

这是反余弦函数的主值范围。余弦函数在[0, π]区间内是单调的(从1递减到-1),因此在这个区间内定义的反函数是单值的。选择[0, π]作为主值范围是数学上的标准约定,这样acos()函数对于每个输入都有唯一确定的输出。

由于浮点数的精度限制,数学上本应在[-1,1]范围内的值可能略微超出。解决方法:

  1. 使用max(-1, min(1, $value))将值限制在范围内
  2. 设置一个很小的epsilon值(如1e-15),当|value-1| < epsilon时视为1
  3. 使用高精度数学库(如bcmath)进行关键计算
  4. 在比较浮点数时使用容差值而不是精确相等