比较NSDecimalNumber的不同方法

例如,用原始的,我会做这个

if ( (x >= 6000) && (x <= 20000) ) // do something here 

和NSDecimalNumber,这是我有

 if ( (([x compare:[NSNumber numberWithInt:6000]] == NSOrderedSame) || ([x compare:[NSNumber numberWithInt:6000]] == NSOrderedDescending)) && (([x compare:[NSNumber numberWithInt:20000]] == NSOrderedSame) || ([x compare:[NSNumber numberWithInt:6000]] == NSOrderedAscending)) ) { // do something here } 

有没有其他的方式(更简单,更优雅)比较? 如果我把这个值转换为原始的,我会用什么原始的? 我不想使用CGFloat,float或double,因为我在这里处理货币。 或者如果我把它们转换成上面提到的那些,有人可以validation/解释精度吗?

我的理解是,你只能使用compare:方法来比较NSDecimalNumberNSNumber对象。 超级沮丧,但我相信这是源于Objective-C不支持运算符重载。

如果阅读变得非常困难,你总是可以用一些帮助方法添加一个类来尝试使其更具可读性,这可能是这样的吗?

 // NSNumber+PrimativeComparison.m - (NSComparisonResult) compareWithInt:(int)i{ return [self compare:[NSNumber numberWithInt:i]] } - (BOOL) isEqualToInt:(int)i{ return [self compareWithInt:i] == NSOrderedSame; } - (BOOL) isGreaterThanInt:(int)i{ return [self compareWithInt:i] == NSOrderedDescending; } - (BOOL) isGreaterThanOrEqualToInt:(int)i{ return [self isGreaterThanInt:i] || [self isEqualToInt:i]; } - (BOOL) isLessThanInt:(int)i{ return [self compareWithInt:i] == NSOrderedAscending; } - (BOOL) isLessThanOrEqualToInt:(int)i{ return [self isLessThanInt:i] || [self isEqualToInt:i]; } 

然后,事情变得更加人性化:

 if([x isGreaterThanOrEqualToInt:6000] && [x isLessThanOrEqualToInt:20000]){ //... } 

编辑我刚刚注意到,你也问了为什么在货币scheme中使用NSDecimalNumber是最优的。 这个答案给出了一个相当不错的原因,这就是为什么浮点数(和双精度)在处理货币时不够精确。 此外, Apple的NSDecimalNumber文档build议在您进行10进制算术时使用它。

 if(([x doubleValue]>=6000.0f) && ([x doubleValue] <=20000.0f)) 

我认为这也会相当不完善。

compare方法返回NSOrderedDescendingNSOrderedAscendingNSOrderedSame

相反,你可以很容易地写

 if ( [x compare:[NSNumber numberWithInt:6000]] != NSOrderedAscending && [x compare:[NSNumber numberWithInt:20000]] != NSOrderedDescending ) { // do something here } 

这是轻微更好的可读性。

NSDecimalNumber +比较类别代码

 @interface NSDecimalNumber (Comparison) - (BOOL)isLessThan:(NSDecimalNumber *)decimalNumber; - (BOOL)isLessThanOrEqualTo:(NSDecimalNumber *)decimalNumber; - (BOOL)isGreaterThan:(NSDecimalNumber *)decimalNumber; - (BOOL)isGreaterThanOrEqualTo:(NSDecimalNumber *)decimalNumber; - (BOOL)isEqualToDecimalNumber:(NSDecimalNumber *)decimalNumber; @end @implementation NSDecimalNumber (Comparison) - (BOOL)isLessThan:(NSDecimalNumber *)decimalNumber { return [self compare:decimalNumber] == NSOrderedAscending; } - (BOOL)isLessThanOrEqualTo:(NSDecimalNumber *)decimalNumber { return [self compare:decimalNumber] != NSOrderedDescending; } - (BOOL)isGreaterThan:(NSDecimalNumber *)decimalNumber { return [self compare:decimalNumber] == NSOrderedDescending; } - (BOOL)isGreaterThanOrEqualTo:(NSDecimalNumber *)decimalNumber { return [self compare:decimalNumber] != NSOrderedAscending; } - (BOOL)isEqualToDecimalNumber:(NSDecimalNumber *)decimalNumber { return [self compare:decimalNumber] == NSOrderedSame; } @end 

单位testing的好措施

 @interface NSDecimalNumber_Comparison_Tests : XCTestCase @end @implementation NSDecimalNumber_Comparison_Tests #pragma mark - isLessThan: tests - (void)test_isLessThan_whenGreaterThan_returnsNO { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6779"]; BOOL result = [decimalNumberA isLessThan:decimalNumberB]; XCTAssertFalse(result); } - (void)test_isLessThan_whenLessThan_returnsYES { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6781"]; BOOL result = [decimalNumberA isLessThan:decimalNumberB]; XCTAssertTrue(result); } - (void)test_isLessThan_whenEqualTo_returnsNO { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; BOOL result = [decimalNumberA isGreaterThan:decimalNumberB]; XCTAssertFalse(result); } #pragma mark - isLessThanOrEqualTo: tests - (void)test_isLessThanOrEqualTo_whenGreaterThan_returnsNO { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6779"]; BOOL result = [decimalNumberA isLessThanOrEqualTo:decimalNumberB]; XCTAssertFalse(result); } - (void)test_isLessThanOrEqualTo_whenLessThan_returnsYES { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6781"]; BOOL result = [decimalNumberA isLessThanOrEqualTo:decimalNumberB]; XCTAssertTrue(result); } - (void)test_isLessThanOrEqualTo_whenEqualTo_returnsYES { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; BOOL result = [decimalNumberA isLessThanOrEqualTo:decimalNumberB]; XCTAssertTrue(result); } #pragma mark - isGreaterThan: tests - (void)test_isGreaterThan_whenGreaterThan_returnsYES { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6779"]; BOOL result = [decimalNumberA isGreaterThan:decimalNumberB]; XCTAssertTrue(result); } - (void)test_isGreaterThan_whenLessThan_returnsNO { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6781"]; BOOL result = [decimalNumberA isGreaterThan:decimalNumberB]; XCTAssertFalse(result); } - (void)test_isGreaterThan_whenEqualTo_returnsNO { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; BOOL result = [decimalNumberA isGreaterThan:decimalNumberB]; XCTAssertFalse(result); } #pragma mark - isGreaterThanOrEqualTo: tests - (void)test_isGreaterThanOrEqualTo_whenGreaterThan_returnsYES { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6779"]; BOOL result = [decimalNumberA isGreaterThanOrEqualTo:decimalNumberB]; XCTAssertTrue(result); } - (void)test_isGreaterThanOrEqualTo_whenLessThan_returnsNO { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6781"]; BOOL result = [decimalNumberA isGreaterThanOrEqualTo:decimalNumberB]; XCTAssertFalse(result); } - (void)test_isGreaterThanOrEqualTo_whenEqualTo_returnsYES { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; BOOL result = [decimalNumberA isGreaterThanOrEqualTo:decimalNumberB]; XCTAssertTrue(result); } #pragma mark - isEqualToDecimalNumber: tests - (void)test_isEqualToDecimalNumber_whenGreaterThan_returnsNO { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6779"]; BOOL result = [decimalNumberA isEqualToDecimalNumber:decimalNumberB]; XCTAssertFalse(result); } - (void)test_isEqualToDecimalNumber_whenLessThan_returnsNO { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6781"]; BOOL result = [decimalNumberA isEqualToDecimalNumber:decimalNumberB]; XCTAssertFalse(result); } - (void)test_isEqualToDecimalNumber_whenEqualTo_returnsYES { NSDecimalNumber *decimalNumberA = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; NSDecimalNumber *decimalNumberB = [NSDecimalNumber decimalNumberWithString:@"4.6780"]; BOOL result = [decimalNumberA isEqualToDecimalNumber:decimalNumberB]; XCTAssertTrue(result); } @end