c++三角函数均使用弧度制,角度需转弧度(×π/180),推荐c++20的std::numbers::pi;优先用atan2(y,x)而非atan(y/x);linux/macos编译需链接-m,浮点比较须用epsilon容差。

sin() 和 cos() 必须传弧度,不是角度
直接用 sin(90) 得到的不是 1,而是 sin(90 弧度) ≈ 0.894 —— 这是新手最常踩的坑。C++ 标准库所有三角函数(sin、cos、tan、asin、acos)都只认弧度。
换算很简单:角度转弧度 = 角度 × π / 180。别手写 3.14159,用 M_PI(需定义 _USE_MATH_DEFINES)或更稳妥的 std::numbers::pi(C++20):
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
int main() {
double deg = 90.0;
double rad = deg * M_PI / 180.0;
std::cout << sin(rad) << "\n"; // 输出接近 1
}-
M_PI不是 C++ 标准,部分编译器(如 macOS clang)默认不提供,加#define _USE_MATH_DEFINES再#include <cmath></cmath> - C++20 起推荐用
std::numbers::pi,无需宏,但得开-std=c++20 - 别用
float版本(如sinf)除非明确需要性能且接受精度损失;默认用double参数和返回值
atan2(y, x) 比 atan(y/x) 安全得多
atan2 是你处理方向、角度差、极坐标转换时真正该用的函数。它能自动判断象限、避开除零、处理边界情况;而 atan(y/x) 只返回 -π/2 到 π/2,一除零就崩,x=0 时完全失效。
典型场景:已知向量分量 dx、dy,求与 x 轴夹角(-π 到 π):
立即学习“C++免费学习笔记(深入)”;
double dx = -3.0, dy = 4.0; double angle = atan2(dy, dx); // 返回约 2.214(即 126.87°),正确落在第二象限
- 参数顺序是
atan2(y, x),不是atan2(x, y)—— 记成“y over x”的比值逻辑,但函数名里 y 在前 - 当
x == 0 && y > 0,返回M_PI_2;x == 0 && y 返回 <code>-M_PI_2;x == 0 && y == 0行为未定义(实际多为 0,但别依赖) - 结果范围是 (-π, π],如果需要 [0, 2π),可做一次归一化:
angle = fmod(angle + 2*M_PI, 2*M_PI)
编译时链接 math 库不是默认行为
在 Linux/macOS 用 g++/clang++ 编译含 sin、atan2 的代码,不加 -lm 会报 undefined reference to 'sin' 或类似链接错误。Windows MSVC 通常不强制要求,但 MinGW 会。
- g++ example.cpp -o example -lm
- clang++ example.cpp -o example -lm
- CMake 中要写
target_link_libraries(mytarget m) - 现代 CMake(3.19+)可用
find_library(MATH_LIB m)加容错,但多数项目直接写m就够用
浮点误差会让角度比较出问题
用 == 直接比较两个 atan2 结果是否相等?大概率翻车。比如 atan2(1, 1) 理论是 π/4,但二进制浮点无法精确表示,实际值有微小偏差。
- 角度比较一律用误差容忍(epsilon):
abs(a - b) 或更鲁棒的 <code>abs(sin(a - b)) (避免跨 ±π 边界) - 涉及周期性(比如判断是否相差 180°),先用
fmod归一化再比:auto diff = fmod(abs(a - b), 2*M_PI); if (diff > M_PI) diff = 2*M_PI - diff; - 不要对
sin/cos输出做精确等值判断(如if (cos(theta) == 0)),改用abs(cos(theta))
C++ 三角函数本身不难,难的是弧度/角度混用、链接遗漏、浮点比较这三处——它们不出错则已,一出就是深夜调试两小时那种。









