16

例如,对于原始的,我会这样做

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,因为我在这里处理货币。或者,如果我确实将它们转换为上述那些,有人可以验证/解释精度吗?

4

4 回答 4

27
于 2012-01-27T07:03:31.647 回答
7

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

良好度量的单元测试

@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
于 2017-03-29T12:51:43.557 回答
3

compare方法返回NSOrderedDescendingNSOrderedAscendingNSOrderedSame

相反,您可以轻松编写

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

哪个可读性更好。

于 2014-12-09T15:00:30.373 回答
2
if(([x doubleValue]>=6000.0f) && ([x doubleValue] <=20000.0f))

我认为这也会相当精确。

于 2012-01-27T07:24:45.350 回答