NSNumber类方法可以在signed和unsigned int之间进行辨别吗?

时间:2011-04-27 22:00:41

标签: objective-c

有没有办法探测NSNumber以查看它是int还是unsigned int。我试图用objCType做这个,但我无法区分。请考虑以下情形:

NSNumber *number1 = [NSNumber numberWithUnsignedInt:100];
NSNumber *number2 = [NSNumber numberWithInt:100];

NSLog(@"%@",[NSString stringWithUTF8String:[number1 objCType]]);
NSLog(@"%@",[NSString stringWithUTF8String:[number2 objCType]]);

输出: 一世 我

有人知道如何解决这个问题吗?

5 个答案:

答案 0 :(得分:2)

为什么这是一个问题?

NSNumber,简单地说,不关心号码是否未签名或签名,并将根据需要强制或转换;就像它不关心数字是固定的还是浮点数一样。

数字的类型只对创作非常重要。

答案 1 :(得分:2)

objCType并不保证它返回的类型与您输入的类型相同。

你要做的事基本上忽略了NSNumber的要点,这是为了避免在C中需要处理数值的笨拙。通过在NSNumber中包装数值,您可以将其与任何其他此类值进行比较,而不考虑其“实际”(按位)类型,并且您可以使用与您开始时不同的“实际”类型返回值。*

它并没有给你完全相同的类型,因为它不需要 - 你输入任何你想要的东西,并取出你想要的任何东西。无论如何,C变量的类型在运行时是未知的。

我猜你必须使用NSNumber,因为你需要将数值粘贴到Cocoa集合中?您可能必须将NSNumber包装在您自己的对象中,该对象也会记录初始类型。这需要很长的switch或一堆if / else ...


*这里唯一需要注意的是,现在您必须再次关注类型的大小:尝试将大于FLT_MAX的值放入float,例如,给出你好垃圾。

答案 2 :(得分:2)

没有。在引擎盖下NSNumber使用CFNumber,而后者不存储无符号值 - NSNumber方法检查传入的值,如果它太大而不适合它使用的相同大小的签名类型下一个较大的签名类型。 (是的,如果存储大的无符号64位整数NSNumber则使用内部128位有符号整数。)

如果您想跟踪原始类型,您必须自己动手,例如:创建一个对象,其中包含类型的字段和数字的字段...

答案 3 :(得分:1)

您可以使用类别扩展NSNumber

@implements NSNumber (Signed)
    - (BOOL)isNumberSigned {
        // Test if number less than zero
        // return the result
    }

这就是Objective-C的美丽;扩展一个类非常简单。

答案 4 :(得分:0)

使用[- doubleValue][- stringValue][- decimalValue]可以显示使用签名的init方法创建时原始值是否为负值。 我很惊讶没有简单的- wasCreatedSigned功能。

BOOL negTest;
negTest = ([myNSNumber doubleValue] < 0);                 // <0.1 micro sec
negTest = [[myNSNumber stringValue] hasPrefix:@"-"];      // >1.5 micro sec
negTest = ([myNSNumber decimalValue]._isNegative);        // >2.5 micro sec
negTest = ([myNSDecimalNumber decimalValue]._isNegative); // <0.1 micro sec

内部NSNumber IS知道其值的签名状态。

至于-objCType我注意到它并不总是反映出init类型,正如文档所说。但它会准确地区分浮点/双打(d)与整数(c,s,i,q,Q ......)。

以下是一些可以使用的代码,它会显示一些奇怪的东西(在iOS 4.3上测试过):

void isNeg(NSNumber* num, NSString* initMethod);
void isNeg(NSNumber* num, NSString* initMethod)
{
    printf("\r");
    NSLog(@"%@ (class:%@)", initMethod, [num class]);

    double dval = [num doubleValue];
    NSLog(@"Is Negative:%c, objCType:%s", (dval<0)?'Y':'N', [num objCType]);
    NSLog(@"strVal: %@", [num stringValue]);
    NSLog(@"%%f    : %f", dval);
    NSLog(@"%%g    : %g", dval);
    NSLog(@"%%lld  : %lld", [num longLongValue]);
    NSLog(@"%%llu  : %llu", [num unsignedLongLongValue]);
}

// main...
double testDouble = 10001e-9;
Class nc = [NSNumber class];

isNeg([nc numberWithChar:    -1], @"Char");
isNeg([nc numberWithChar:    -2], @"Char");
isNeg([nc numberWithChar:    -3], @"Char");
isNeg([nc numberWithChar:     1], @"Char");
isNeg([nc numberWithChar:    12], @"Char");
isNeg([nc numberWithChar:    13], @"Char");
isNeg([nc numberWithUnsignedChar: 12], @"UChar");
isNeg([nc numberWithUnsignedChar: 13], @"UChar");

isNeg([nc numberWithLongLong:        -LONG_LONG_MAX], @"LongLong");
isNeg([nc numberWithLongLong:         LONG_LONG_MAX], @"LongLong");
isNeg([nc numberWithUnsignedLongLong: ULONG_LONG_MAX], @"ULongLong");

isNeg([nc numberWithDouble:-LONG_LONG_MAX], @"Double");
isNeg([nc numberWithDouble: ULONG_LONG_MAX], @"Double");

isNeg([nc numberWithDouble:-testDouble], @"Double");
isNeg([nc numberWithDouble: testDouble], @"Double");

nc = [NSDecimalNumber class];
isNeg([nc numberWithDouble:-testDouble], @"Double");
isNeg([nc numberWithDouble: testDouble], @"Double");