NSDecimalNumber的准确性和比较

时间:2013-09-12 21:51:12

标签: objective-c cocoa-touch cocoa

在以下测试代码中,断言失败

NSDecimalNumber *num1 = [[NSDecimalNumber alloc] initWithInteger:1];
NSDecimalNumber *num2 = [[NSDecimalNumber alloc] initWithInteger:6];
NSDecimalNumber *num3 = [[NSDecimalNumber alloc] initWithInteger:3];
NSDecimalNumber *result1 = [num1 decimalNumberByDividingBy:num2]; // 1 ÷ 6
NSDecimalNumber *result2 = [result1 decimalNumberByMultiplyingBy:num3]; // 1 ÷ 6 x 3 = 0.5

NSDecimalNumber *num4 = [[NSDecimalNumber alloc] initWithFloat:0.5];
NSAssert([result2 compare:num4] == NSOrderedSame, @"Math error");

我理解这与浮点精度有关,1÷6会引入问题。结果2是0.49999999999999999999999999999999999998而不是0.5。

我试图验证两个数学表达式给出相同的结果。我不应该为此目的使用比较,而是允许两个NSDecimalNumbers之间的一些小的小数差异?或者也许我应该使用decimalNumberByDividingBy:withBehavior:方法并进行一些舍入? 我不知道如何最好地继续。理想情况下,结果2将是0.5,我不需要破解比较。

编辑:我正在考虑在比较阶段使用容差方法(不理想) -

- (NSDecimalNumber *)abs:(NSDecimalNumber *)num {
    if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
        // Number is negative. Multiply by -1
        NSDecimalNumber * negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1
                                                                      exponent:0
                                                                    isNegative:YES];
        return [num decimalNumberByMultiplyingBy:negativeOne];
    } else {
        return num;
    }
}

- (void)test {
    NSDecimalNumber *num1 = [[NSDecimalNumber alloc] initWithInteger:1];
    NSDecimalNumber *num2 = [[NSDecimalNumber alloc] initWithInteger:6];
    NSDecimalNumber *num3 = [[NSDecimalNumber alloc] initWithInteger:3];
    NSDecimalNumber *result1 = [num1 decimalNumberByDividingBy:num2]; // 1 ÷ 6
    NSDecimalNumber *result2 = [result1 decimalNumberByMultiplyingBy:num3]; // 1 ÷ 6 x 3 = 0.5

    NSDecimalNumber *num4 = [[NSDecimalNumber alloc] initWithFloat:0.5];
    NSDecimalNumber *tolerance = [[NSDecimalNumber alloc] initWithFloat:0.000000000001];
    NSDecimalNumber *delta = [self abs:[result2 decimalNumberBySubtracting:num4]];
    NSAssert([delta compare:tolerance] == NSOrderedAscending, @"Math error");
}

0 个答案:

没有答案