我是单元测试的新手,我决定编写一个简单的计算器来研究这些概念,但是我遇到了一个对我来说毫无意义的问题。 STAssertEquals失败了2个显然相同的double值。 我得到的错误就是这个: '-2.89'应该等于'-2.89':
执行计算的代码是:
- (double)calculateOperation:(int)operation numberA:(double)numA numberB:(double)numB
{
double result = 0;
switch(operation)
{
case addition:
result = numA + numB;
break;
case subtraction:
result = numA - numB;
break;
case multiplication:
result = numA * numB;
default:
break;
}
return result;
}
测试是
- (void)testSubtraction
{
//Two double positive values
double test1 = [calculator calculateOperation:subtraction numberA:4.45 numberB:7.34];
STAssertEquals(test1, -2.89, nil);
}
我尝试使用不同的值,似乎只有一定范围的值会导致STAssertEquals失败。
但是,如果我执行STAssertEquals((4.45 - 7.34), - 2.89,nil)它的工作没有任何问题。
我真的不知道出了什么问题。
答案 0 :(得分:2)
考虑以下设置:
double a = 4.45;
double b = 7.34;
double result = a - b;
double testVal = -2.89;
此时,如果您查看result
与testVal
的内存中的实际值,您会看到以下内容:
(lldb) p/x *(uint64_t*)&testVal
(uint64_t) $1 = 0xc0071eb851eb851f
(lldb) p/x *(uint64_t*)&result
(uint64_t) $2 = 0xc0071eb851eb851e
所以你可以看到确实存在差异,可能是由于减法运算中的舍入,在<{1}}的有效数的最后一位与我们放置的文字之间存在差异在result
。当格式化代码将本机二进制表示转换为十进制时,这种差异可能不明显,因为这些转换并不总是精确,但它仍然会影响这两个值的文字相等。
实际上,您可能希望在此使用testVal
,为您的应用选择适合的准确度值。 (对于图形工作,我通常使用1e-6,但你的里程可能会有所不同。)此外,由于所有内容都是STAssertEqualsWithAccuracy
,因此您不需要在此处进行显式转换。编译器将没有后缀的十进制数字文字解释为double
(如果您希望double
跟随带有F的十进制数字文字,并且如果您想要float
,请按照它用L.即-2.89F或-2.89L)
值得重申的是:虽然许多人喜欢在十进制参考框架中考虑浮点数(因为这是我们大多数人学习算术的方式),但这不是它们的存储方式,而不是“它们如何工作”。如果你不希望它们表现得像10号基数,那么你会失望得多。这是一个典型的例子。