arc4random_uniform在转换为float时产生非常大的值

时间:2021-01-25 13:28:07

Blank project. Code:

空白项目。码:

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

Log:

日志:

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 is clearly outside the range of 100 - ran(200) (pseudocode)

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

If I don't declare amount as float and instead use int this doesn't happen.

如果我没有将amount声明为float而是使用int,则不会发生这种情况。

What's going on here?

这里发生了什么?

1 个解决方案

#1


1  

As @rob points out, arc4random_uniform returns a 32-bit unsigned integer type (uint32_t), that is, a number greater than or equal to zero, never negative. The compiler thus evaluates the expression 100-arc4random_uniform(200) expecting the result also to be an unsigned number.

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

If the result of arc4random_uniform(200) in your example code happens to be greater than 100, then 100-arc4random_uniform(200) will result in a negative number being assigned to a data type that cannot express negative numbers, so you'll end up with unexpected results.

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

You can indicate to the compiler that you want to be dealing with signed numbers by, as @rob suggests, casting the result of arc4random_uniform to a signed number (in this case a float):

你可以向编译器指出你想要处理有符号数,正如@rob建议的那样,将arc4random_uniform的结果转换为有符号数(在本例中为float):

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

...or by indicating that the expression should return a signed number by explicitly making your other argument a signed number:

...或者通过明确地将您的其他参数设为带符号的数字来指示表达式应返回带符号的数字:

float amount = 100.0f - arc4random_uniform(200);

#1


1  

As @rob points out, arc4random_uniform returns a 32-bit unsigned integer type (uint32_t), that is, a number greater than or equal to zero, never negative. The compiler thus evaluates the expression 100-arc4random_uniform(200) expecting the result also to be an unsigned number.

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

If the result of arc4random_uniform(200) in your example code happens to be greater than 100, then 100-arc4random_uniform(200) will result in a negative number being assigned to a data type that cannot express negative numbers, so you'll end up with unexpected results.

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

You can indicate to the compiler that you want to be dealing with signed numbers by, as @rob suggests, casting the result of arc4random_uniform to a signed number (in this case a float):

你可以向编译器指出你想要处理有符号数,正如@rob建议的那样,将arc4random_uniform的结果转换为有符号数(在本例中为float):

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

...or by indicating that the expression should return a signed number by explicitly making your other argument a signed number:

...或者通过明确地将您的其他参数设为带符号的数字来指示表达式应返回带符号的数字:

float amount = 100.0f - arc4random_uniform(200);