Objective c 比较小数的不同方法
例如,对于primitive,我将这样做Objective c 比较小数的不同方法,objective-c,ios,nsdecimalnumber,Objective C,Ios,Nsdecimalnumber,例如,对于primitive,我将这样做 if ( (x >= 6000) && (x <= 20000) ) // do something here 有没有其他方法(更简单、更优雅)来进行比较?如果我将值转换为基元,我应该使用什么基元?我不想使用CGFloat、float或double,因为我在这里处理的是货币。或者,如果我将它们转换为上面提到的那些,有人能验证/解释精度吗?我的理解是,您只能使用比较:方法比较NSDecimalNumber和NSNum
if ( (x >= 6000) && (x <= 20000) )
// do something here
有没有其他方法(更简单、更优雅)来进行比较?如果我将值转换为基元,我应该使用什么基元?我不想使用CGFloat、float或double,因为我在这里处理的是货币。或者,如果我将它们转换为上面提到的那些,有人能验证/解释精度吗?我的理解是,您只能使用
比较:
方法比较NSDecimalNumber
和NSNumber
对象。超级令人沮丧,但我相信它源于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]){
//...
}
编辑我刚刚注意到,您还询问了为什么在货币方案中使用NSDecimalNumber是最佳选择。给出了一个很好的例子,解释了为什么在使用货币时浮动(和双倍)不够精确。此外,建议您在执行base-10算术时使用它。
如果([x doubleValue]>=6000.0f)和([x doubleValue]compare
方法返回sensorderedescing
,sensorderedescing
或sensorderedsame
if(([x doubleValue]>=6000.0f) && ([x doubleValue] <=20000.0f))
相反,你可以很容易地写
if (
[x compare:[NSNumber numberWithInt:6000]] != NSOrderedAscending &&
[x compare:[NSNumber numberWithInt:20000]] != NSOrderedDescending
)
{
// do something here
}
可读性稍好。NSDecimalNumber+比较类别代码
良好度量的单元测试
我相信double的精度只有15位左右,而NSDecimalNumber大约是38位。因为他在处理货币问题,所以最好还是谨慎一点,在这里使用最精确的数字表示法。事实上,这更好地解释了浮点(和double)的原因数学不够精确,无法用于货币计算。在本例中,他将其与整数进行比较,因此我认为[x intValue]也可以。这就是所需的精度。如果您需要一个简单的旧整数,为什么要首先使用重量级的NSDecimalNumber?小提示:If([x compare:[NSNumber numberWithInt:6000])!=NSorDeredescending)和([x比较:[NSNumber Withint:20000]]!=NSorDeredescending))
给出相同的结果。“大于或等于”等于“不小于”.谢谢!我一直在考虑类似的事情,但老实说,我仍然不喜欢做这个简单的操作有多困难。我关于精度的问题更像是,如果我将它们转换为原语以进行比较,是否有人可以证明它在精度方面是安全的。CGFloat是用二进制格式表示的,w这在处理钱的时候不是很精确。谢谢!
if (
[x compare:[NSNumber numberWithInt:6000]] != NSOrderedAscending &&
[x compare:[NSNumber numberWithInt:20000]] != NSOrderedDescending
)
{
// do something here
}
@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