随机数生成
今天课上学习了猜数字游戏的实现,用到随机数,但只是生成1~100之间的随机数,感觉比较简单。课后想到,如果想生成更大范围的随机数,应该怎么做呢?例如生成介于min 和 max之间的随机数,应该怎么实现?下来仔细思考了一下,发现还是有点意思的。现在将思路记录下来。
思路
首先考虑min 和 max的范围,这个完全可以转换成min + (0,max-min)这个即可。所以我们至需要考虑0~(max-min)之间即可。C语言中,rand
函数只能生成最大值为32767
的随机数,超过这个范围可能需要一些运算才能实现。
我们先观察一个比较大的数字,例如654321
。这个数字可以写成65X100001 + 4321X100000 。那么我们可以生成0至4321之间的随机数sum0
,然后再生成0至65之间的随机数sum1
,然后按照ret = sum1X100001 +sum2X100000 将这两个值加起来就可以得到最后想要的数字了。有了这个思路,尝试写一下代码。
计算指数
根据上面的思路,先计算指数。指数这里比较简单,数字的位数如果<=4,指数为0,否则的话指数为位数/4。那么就可以写代码了:
while (max)
{
max /= 10;
digits++;//计算位数
}
int divi = 0;//计算指数
if (digits <= 4)
{
divi = 0;
}
else
divi = digits / 4;
随机数计算
对于任意的数字,我们首先利用%取后4位,然后使用rand()
函数就可以得到0后4位的随机数。然后将这个值/10000,再用%取出后4位,再次利用`rand()`得到0新后4位的随机数,这个数字再*10000,加到之前的数字上。之后就一直重复这个过程,直到最初的数字为0。看一下代码:
while (Max_Init)
{
sum = 0;
for (int i = 0; i <= divi; i++)
{
int sum0 = Max_Init % 10000;//处理整万情况
if (0 == sum0)
{
sum0 = 9999;
}
int sum1 = rand() % sum0;
sum += sum1 * pow(10000, i);
Max_Init /= 10000;
}
}
写代码的时候碰到的坑
- 首先就是碰到类似
50000
这种情况。由于50000%10000 = 0
,那么在计算上述代码中的sum1时,会报错,因此做了判断。如果0==sum0
,说明是整万,那么直接给sum0
赋值9999
就可以了; - 计算指数的时候,位数和指数直接不是 指数 = 位数/4,这个公式仅在位数>4的时候成立,因为如果位数是4,位数/4 = 1,但这里指数是需要为0的(只有4位数)。
看一下完整的代码(方便测试写成多组输入了):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int main()
{
srand((unsigned int)time(NULL));
long long min = 0;
long long max = 0;
long long sum = 0;
while (scanf("%lld %lld", &min, &max) != EOF)
{
max = max - min;
long long Max_Init = max;
int digits = 0;
//数位数
while (max)
{
max /= 10;
digits++;//计算位数
}
int divi = 0;
if (digits <= 4)
{
divi = 0;
}
else
divi = digits / 4;
while (Max_Init)
{
sum = 0;
for (int i = 0; i <= divi; i++)
{
int sum0 = Max_Init % 10000;
if (0 == sum0)
{
sum0 = 9999;
}
int sum1 = rand() % sum0;
sum += sum1 * pow(10000, i);
Max_Init /= 10000;
}
}
sum += min;
printf("%lld\n", sum);
}
return 0;
}
运行结果:
一些说明
没有参考任何资料,也没有去看别人的代码。我相信一定有比我这种方法更加优秀的方法,这里只是作为一个小小的扩展练习。