比较NSDecimalNumber的不同方法

X S*_*ash 15 objective-c nsdecimalnumber ios

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

if ( (x >= 6000) && (x <= 20000) )
    // do something here 
Run Code Online (Sandbox Code Playgroud)

并且使用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
}
Run Code Online (Sandbox Code Playgroud)

这种比较还有其他方法(更简单,更优雅)吗?如果我将值转换为原始,我使用什么原语?我不想使用CGFloat,float或double,因为我在这里处理货币.或者如果我将它们转换为上面提到的那些,有人可以验证/解释精度吗?

the*_*RON 25

我的理解是你只能比较NSDecimalNumberNSNumber使用该compare:方法的对象.超级令人沮丧,但我认为它源于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];
}
Run Code Online (Sandbox Code Playgroud)

然后事情变得更具人性化:

if([x isGreaterThanOrEqualToInt:6000] && [x isLessThanOrEqualToInt:20000]){
    //...
}
Run Code Online (Sandbox Code Playgroud)

编辑我刚刚注意到你也问过为什么在货币场景中使用NSDecimalNumber是最优的.这个答案很好地说明了为什么浮点数(和双打数)在使用货币时不够精确.此外,Apple的NSDecimalNumber文档建议在您进行base-10算术时使用它.


Oli*_*ain 5

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
Run Code Online (Sandbox Code Playgroud)

单位测试以获得良好的衡量标准

@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
Run Code Online (Sandbox Code Playgroud)