即使a1 = a2,STAssertEquals也会失败

时间:2013-06-11 10:13:57

标签: objective-c unit-testing

我是单元测试的新手,我决定编写一个简单的计算器来研究这些概念,但是我遇到了一个对我来说毫无意义的问题。 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)它的工作没有任何问题。

我真的不知道出了什么问题。

1 个答案:

答案 0 :(得分:2)

考虑以下设置:

double a = 4.45;
double b = 7.34;
double result = a - b;
double testVal = -2.89;

此时,如果您查看resulttestVal的内存中的实际值,您会看到以下内容:

(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号基数,那么你会失望得多。这是一个典型的例子。