【问题标题】:arc4random_uniform producing very large values when casting to floatarc4random_uniform 在转换为浮动时产生非常大的值
【发布时间】:2017-06-12 14:06:38
【问题描述】:

空白项目。代码:

int i = 0;
while (i < 8) {
    float amount = 100-arc4random_uniform(200);
    NSLog(@"amount: %f", amount);
    i++;
}

日志:

amount: 21.000000
amount: 90.000000
amount: 79.000000
amount: 4294967296.000000
amount: 39.000000
amount: 4294967296.000000
amount: 81.000000
amount: 4294967296.000000

4294967296.000000 明显超出100 - ran(200) 的范围(伪代码)

如果我不将 amount 声明为 float 而是使用 int 这不会发生。

这是怎么回事?

【问题讨论】:

  • arc4random 返回无符号整数。在进行减法之前将其转换为(有符号)整数或双精度数。
  • @Rob 谢谢!是否有任何直观的方法来判断什么时候要签名和未签名,或者我只需要检查文档。我没有接受过正式的代码培训,只是通过阅读源代码来了解我所知道的一切,所以我还不知道有符号和无符号之间的区别;我假设它与数字前面的 ± sign (或缺少“无符号”)有关。
  • 标准 32 位 int 可以表示介于 -2,147,483,648 和 2,147,483,647 之间的值,但 unsigned int 只能表示介于 0 和 4,294,967,295 之间的值(即 2 的 32 次方,负 1) .因此,如果您从无符号整数值 0 中减去 1,因为它不能表示 -1,它会回绕到 4,294,967,295。关于如何知道,我唯一可以建议的是,如果您在左侧保持“快速帮助”面板打开,则可以更轻松地确认方法返回的类型。遗憾的是,开发人员有责任确认方法的签名。
  • 所以当你有一个不能返回负数的方法(例如一个返回一个介于 0 和某个正整数之间的值的函数)时,要认识到它可能是无符号的,所以做一个记住检查它返回的类型(尤其是当您编写的代码依赖于它是有符号还是无符号时)。
  • 好指针,谢谢@Rob

标签: objective-c casting floating-point integer arc4random


【解决方案1】:

正如@rob 指出的那样,arc4random_uniform 返回一个 32 位无符号整数类型 (uint32_t),即大于或等于零的数字,绝不是负数。编译器因此计算表达式100-arc4random_uniform(200),期望结果也是一个无符号数。

如果您的示例代码中 arc4random_uniform(200) 的结果恰好大于 100,则 100-arc4random_uniform(200) 将导致将负数分配给无法表示负数的数据类型,因此您最终会得到意想不到的结果。

您可以向编译器表明您希望处理带符号的数字,正如@rob 建议的那样,将arc4random_uniform 的结果转换为带符号的数字(在本例中为float):

float amount = 100 - (float)arc4random_uniform(200);

...或通过显式使您的其他参数成为有符号数来指示表达式应返回有符号数:

float amount = 100.0f - arc4random_uniform(200);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    • 2018-04-01
    • 1970-01-01
    相关资源
    最近更新 更多