为什么其中一些工作不起作用的确切原因是什么?

时间:2019-04-19 22:33:24

标签: c++

其中一些仅吐出0,而其他一些吐出正确的随机数。我认为这与将它们强制转换为无符号整数并丢弃小数部分有关,但是强制转换到底在哪里进行?

#include <cstdlib> #include <ctime> #include <iostream> const unsigned NUM_MIN {0}; const unsigned NUM_MAX {50}; int main () { // Seed random number generator. std::srand(static_cast<unsigned>(time(nullptr))); size_t times {}; do { // Get a random number between NUM_MIN and NUM_MAX. unsigned number {NUM_MIN + std::rand() / ((RAND_MAX + 1u) / NUM_MAX)}; // Works // unsigned number {NUM_MIN + std::rand() / (RAND_MAX / NUM_MAX)}; // Works. // unsigned number {NUM_MIN + (std::rand() / RAND_MAX) / NUM_MAX}; // Does not work. // unsigned number {NUM_MIN + std::rand() / RAND_MAX / NUM_MAX}; // Does not work. // unsigned number {NUM_MIN + (std::rand() / RAND_MAX) * NUM_MAX}; // Also does not work. // unsigned number {NUM_MIN + (std::rand() / (RAND_MAX + 1u)) * NUM_MAX}; // Doesn't work. std::cout << number << std::endl; } while (++times < 20); return EXIT_SUCCESS; }

1 个答案:

答案 0 :(得分:2)

并不是在所有情况下都是“问题”。

还有一个事实是整数除法会产生积分结果。对于正操作数,四舍五入总是朝着零。

不同操作数具有不同优先级的事实。乘法和除法比加法和减法具有更高的优先级(并且所有算法都具有从左到右的关联性)。方括号()用于覆盖。

unsigned number {NUM_MIN + std::rand() / ((RAND_MAX + 1u) / NUM_MAX)};  

RAND_MAX转换为unsigned(因为已将其添加到1u中)。然后,由于两个操作数均为unsigned,因此((RAND_MAX + 1u) / NUM_MAX)产生类型为unsigned的结果。 std::rand()的结果将转换为unsigned。表达式中的所有其他运算都有unsigned个操作数,并产生unsigned个结果。

unsigned number {NUM_MIN + std::rand() / (RAND_MAX / NUM_MAX)};

RAND_MAX被转换为unsigned,所以(RAND_MAX / NUM_MAX)产生类型为unsigned的结果。然后将std::rand()转换为unsigned进行除法,此表达式中的所有其他操作都具有unsigned个操作数和unsigned个结果。

unsigned number {NUM_MIN + (std::rand() / RAND_MAX) / NUM_MAX};   
unsigned number {NUM_MIN + std::rand() / RAND_MAX / NUM_MAX};   
unsigned number {NUM_MIN + (std::rand() / RAND_MAX) * NUM_MAX}; 

在所有这三种情况下,std::rand()RAND_MAX都给出类型为int的正值,因此std::rand() / RAND_MAX被计算为int。这将为零,因为RAND_MAXrand()返回的结果的上限。将该零值转换为unsigned以除以NUM_MAX(在第三种情况下是乘法),并且所有其他运算都用unsigned操作数和结果执行。最终结果是number将被初始化为等于NUM_MIN

unsigned number {NUM_MIN + (std::rand() / (RAND_MAX + 1u)) * NUM_MAX};  

这里的逻辑与前面的逻辑相同,除了使用unsigned完成除法之外。

您可能还想重新定义“作品”的定义。您评论为“作品”的两个示例会产生不同的结果。