sqrt要求非负输入,负数返回NaN且可能静默失败;需链接-libm;优先用sqrt/sqrtf而非手写;long double精度跨平台不一致。

用 sqrt 计算平方根,但必须传入非负数
直接调用 sqrt 是最常用做法,但它对负数输入不定义——在大多数平台上会返回 nan(Not a Number),且可能触发浮点异常(取决于编译器和运行时设置)。这不是“报错”,而是静默出错,容易被忽略。
- 正数和零:安全,返回精确到浮点精度的平方根值
- 负数:返回
nan,std::isnan(sqrt(-1))为 true;若开启 FPE 检查(如 GCC 的-ftrapv或某些调试环境),可能中断执行 - 类型要匹配:
sqrt(4)调用的是double sqrt(double),整数会被隐式转成double;想用float版本得写sqrtf(4.0f),否则多一次类型转换
sqrtf 和 sqrtl 的实际差异不只是精度
这三个函数分别对应 float、double、long double 输入/输出。区别不止是“算得更准”,还涉及性能和 ABI 兼容性。
-
sqrtf通常比sqrt快,尤其在向量化场景下(如启用-march=native -ffast-math) -
sqrtl在 x86-64 Linux 上多数实现仍是软件模拟,慢很多;Windows MSVC 下甚至可能退化为double精度 - 跨平台时别假设
long double一定是 80-bit:Clang/LLVM 默认用 IEEE-754 binary64(即等同double)
编译时没链接 libm 会导致 undefined reference to sqrt
这是 Linux/macOS 上高频链接错误。C++ 标准库头文件 <cmath> 声明了 sqrt,但实现体在数学库 libm 中,而 C++ 链接器默认不自动拉它。
- g++/clang++ 编译时需显式加
-lm:例如g++ main.cpp -lm - CMake 用户注意:
target_link_libraries(myapp m)必须写,不能只靠find_package(Threads)之类掩盖 - Windows MSVC 一般无此问题(数学函数内建于 libcmt),但 MinGW-w64 同样要
-lm
替代方案:手写牛顿迭代或查表法只在极端场景有用
除非你在做嵌入式裸机、GPU shader、或对某段热代码做极致优化,否则不要自己实现平方根。现代 sqrt 指令(x86 的 sqrtss/sqrtsd)已高度优化,且编译器能自动向量化循环中的多次调用。
立即学习“C++免费学习笔记(深入)”;
- 牛顿法写出来容易,但收敛性、初值选择、边界处理(比如 0、极小值)全是坑
- 查表法内存占用大,缓存不友好,且插值误差难控
- 唯一常见例外:需要整数平方根(如判断是否为完全平方数),这时用
static_cast<int>(std::round(sqrt(n)))再平方验证,比纯整数二分略快但可读性差
-lm、以及误以为 long double 在所有平台都提供扩展精度。








