实习面试:两数相加函数测试方案的优化方法咨询
哈哈,我太懂这种场景了!面试官不满意你的实现,核心问题出在浮点数直接用==比较上——因为浮点数在二进制存储时会有精度损失,哪怕是看起来简单的小数(比如0.1)也没法精确表示,直接相等判断很容易误判。下面给你几种更靠谱的实现方式:
1. 基于容差(Epsilon)的比较法
这是浮点数比较的标准操作,通过判断两个值的差值是否小于一个极小的阈值(epsilon)来确定是否“相等”。代码示例:
#include <cmath> bool addTest(double a, double b) { double expected = a + b; double actual = addFunction(a, b); // 用绝对差值和极小阈值比较 return fabs(expected - actual) < 1e-9; }
如果要处理大数场景(比如极大值相加),可以结合相对误差判断,避免大数的精度偏差:
bool addTest(double a, double b) { double expected = a + b; double actual = addFunction(a, b); double absDiff = fabs(expected - actual); // 取较大值作为分母,避免除以0 double maxVal = fmax(fabs(expected), fabs(actual), 1e-12); double relDiff = absDiff / maxVal; // 绝对误差或相对误差满足一个即可 return absDiff < 1e-9 || relDiff < 1e-9; }
2. 覆盖边界场景的批量测试
面试官可能希望你的测试不仅能验证普通情况,还要覆盖各种边界案例。可以封装一个批量测试函数,覆盖这些场景:
bool runAllAddTests() { bool allPass = true; // 测试正负值相加 allPass &= addTest(100.0, -50.0); // 测试零值组合 allPass &= addTest(0.0, 123.45); allPass &= addTest(0.0, 0.0); // 测试精度敏感的经典案例 allPass &= addTest(0.1, 0.2); // 测试浮点数极值 allPass &= addTest(DBL_MAX, 1.0); // 注意:需确认addFunction对溢出的处理逻辑 allPass &= addTest(DBL_MIN, DBL_MIN); return allPass; }
3. 利用断言简化单元测试
如果是在单元测试场景下,可以用断言直接抛出错误,方便调试:
#include <cassert> #include <cmath> void testAddFunction() { assert(fabs((0.1 + 0.2) - addFunction(0.1, 0.2)) < 1e-9); assert(fabs((100.0 + (-50.0)) - addFunction(100.0, -50.0)) < 1e-9); assert(fabs((0.0 + 0.0) - addFunction(0.0, 0.0)) < 1e-9); // 更多断言... }
4. 处理特殊浮点数(NaN/无穷大)
浮点数还有NaN(非数字)、INF(无穷大)这类特殊值,需要单独处理:
#include <cmath> bool addTest(double a, double b) { double expected = a + b; double actual = addFunction(a, b); // 处理NaN:NaN和任何值都不相等,需用isnan判断 if (isnan(expected)) { return isnan(actual); } // 处理无穷大:需同时判断是正无穷还是负无穷 if (isinf(expected)) { return isinf(actual) && (signbit(expected) == signbit(actual)); } // 普通情况用容差比较 return fabs(expected - actual) < 1e-9; }
总结一下:面试官不满意的核心是你没考虑浮点数的精度特性,以及测试场景的完整性。上面这些方法从精度处理、边界覆盖、特殊值兼容等方面做了改进,应该能符合要求。
内容的提问来源于stack exchange,提问作者Oana Furtună
相关产品推荐
相关产品推荐

