【问题标题】:arc4random in NSNumber giving negative values?NSNumber 中的 arc4random 给出负值?
【发布时间】:2013-03-01 10:04:53
【问题描述】:

我正在创建一个随机数并将其存储在 NSNumber 对象中,如下所示:

NSNumber *index = [NSNumber numberWithUnsignedInt:arc4random_uniform(2^32-1)];

我也试过了:

NSNumber *index = [NSNumber numberWithUnsignedInt:arc4random_uniform(4294967295)];
NSNumber *index = @(arc4random_uniform(4294967295));

有时我也会像这样分配数字 1:

NSNumber *index = @(1);

这应该只给我正数。

稍后,我会像这样打印出这些数字:

NSString *string = [NSString stringWithFormat:@"%@", index];

这给了我一些随机数的负值,并且 1 被打印为 1。所以我可能会这样做:

NSString *string = [NSString stringWithFormat:@"%u", index.unsignedIntValue];

我只会得到正数 - 我会 - 但现在 1 也突然被打印为一些大的正数。

这里发生了什么?如何在 NSNmber 中正确存储 u_int32(arc4random 返回的)并确保它们只是正数?

【问题讨论】:

  • 我应该补充一点,我使用 NSNumber 来存储索引值的原因是它在 NSManagedObject 实体中使用。该实体的属性设置为“Integer 32”(数据模型中没有可用的 Unsigned Integer 32)。
  • 你如何打印你从上一个 sn-p 得到的字符串?为(@1) 获取一个大的正数没有任何意义。可能是您在打印字符串时没有使用正确的格式说明符 (%@)?
  • 顺便说一句,请注意,无符号 32 位整数可以包含比有符号整数更大的值(但不确定这是否对 Core Data 有任何影响)。
  • 我实际上将索引号分配给这样的 uitextlabel: textlabel.text = [NSString stringWithFormat:@"%@", index];或 textlabel.text = [NSString stringWithFormat:@"%u", index.unsignedIntValue];

标签: objective-c nsnumber arc4random


【解决方案1】:

使用

NSNumber *index = [NSNumber numberWithUnsignedInt:arc4random_uniform(exp2(32)-1)];

我从来没有得到任何负数。 arc4random_uniform(x) 总是返回一个介于 0 和 x 之间的数字,并且从中生成的 NSNumber 的字符串值是正确的。

编辑:将 exp2(31) 替换为 exp2(32)

【讨论】:

  • 我现在也改用 2^31-1 而不是 2^32-1,但这意味着我只有一半可用的数字,我不明白为什么 2^32- 1 有时会给出负数...
  • 对不起,这是我的错字。您可以使用exp2(32),它工作正常
【解决方案2】:

您在评论中说索引作为“整数 32”属性存储在核心数据实体中,我认为这就是问题所在。

Core Data 为托管对象类的所有属性(和关系)动态生成 getter 和 setter 方法。这些访问器方法不同于由实例变量支持的“常规”@synthesized 访问器方法。

对于“Integer 32”属性,Core Data 使用(有符号)整数作为属性,当你设置一个值时,它只是被强制转换或截断为int。示例:

e.index = [NSNumber numberWithUnsignedInt:0xFFFFFFF0U];
// This would give the same result:
// e.index = [NSNumber numberWithLongLong:0x1234FFFFFFF0LL];
NSNumber *val = e.index;
NSLog(@"value=%@, type=%s", val, [val objCType]);
// Output: value=-16, type=i

输出type=i 显示该值包含int

如果您需要0 .. 2^32-1 范围内的无符号整数,那么您可以(就像您已经做过的那样)使用unsignedIntValue

unsigned x = [val unsignedIntValue];

或将属性存储为“Integer 64”。

备注:

  • 我很确定这不是arc4random_uniform 的问题。
  • 在您的第一个代码示例arc4random_uniform(2^32-1) 中,您应该注意^ 是异或,而不是求幂。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2012-03-04
    • 1970-01-01
    • 2016-12-29
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多