在C语言中生成随机64/32/16/和8位整数

在C语言中生成随机64/32/16/和8位整数,c,random,bit-manipulation,bit-shift,C,Random,Bit Manipulation,Bit Shift,我希望有人能让我理解为什么代码会这样工作。我正试着把我的头脑集中在一些事情上,但我迷路了 我的教授给了我们这个代码片段,我们必须使用它来生成C语言中的随机数。这个片段会生成一个64位整数,我们必须调整它来生成32位、16位和8位整数。我完全不知道从哪里开始,我不一定要问一个解决方案,只是问原始代码段是如何工作的,这样我就可以在那里调整它 long-rand64() { INTA,b; 长r; a=兰德(); b=兰德(); r=(长)a; r=(r我做了一个相对安全的假设,在计算机的C实现中,l

我希望有人能让我理解为什么代码会这样工作。我正试着把我的头脑集中在一些事情上,但我迷路了

我的教授给了我们这个代码片段,我们必须使用它来生成C语言中的随机数。这个片段会生成一个64位整数,我们必须调整它来生成32位、16位和8位整数。我完全不知道从哪里开始,我不一定要问一个解决方案,只是问原始代码段是如何工作的,这样我就可以在那里调整它

long-rand64()
{
INTA,b;
长r;
a=兰德();
b=兰德();
r=(长)a;

r=(r我做了一个相对安全的假设,在计算机的C实现中,
long
是64位数据类型

这里的关键是,由于
long r
是有符号的,所以设置了最高位的任何值都将是负数。因此,代码将
r
移位31位以避免设置该位

|
是一个逻辑位运算符,它通过在
r
中设置
b
中设置的所有位来组合这两个值

编辑:

阅读了一些评论后,我意识到我的答案需要更正。
rand()
返回的值不超过
rand_MAX
,通常为2^31-1。因此,
r
是31位整数。如果将其向左移位32位,则可以保证其31位(0向上计数)将始终为零。

rand()
生成一个声誉可疑的随机值
[0…rand_MAX]
,但让我们把声誉放在一边,假设
rand()
足够好,并且是一个 (幂-of-2-1)

OP代码的弱点:如果
RAND_MAX==pow(2,31)-1
,则OP的
rand64()
仅返回值[0…pow(2,62))


相反,根据需要多次循环

为了找出每次调用返回的随机比特数,我们需要log2(
RAND_MAX
+1)


rand()
生成一个介于0和
RAND_MAX
之间的数字。在
int
为32位的系统上,过去20年来基本上都是非嵌入式系统,
RAND_MAX
通常为2^31-1,最大的正符号32位整数。当然,这意味着该函数实际上只生成一个随机的62位整数呃。这不是一个随机的63位整数吗?如果原始值填充了32位,然后向左移动31位,那么得到的是63位。@DanielWalker不,每个
rand()
产生31位,所以得到的是62位的值啊,我明白了。天哪,这更有意义!所以对于一个随机的16位整数,我可以调用rand()一次,然后将其向左移动16位?8位也有类似的情况?是的,哈哈,我在打字时脑子里想着教授的实现。但那是正确的吗?是的。你也可以屏蔽你不想要的位。所以,
uint16\u t value=rand()&0x0000ffff;
很高兴听到这个消息。=)
long
根据标准必须至少有64位。但是这里的函数甚至没有填充第63位,更不用说符号位了。事实上,如果需要int64_t范围内的随机值,那么负值必须以与非负值相同的频率出现。没有理由这样做避免使用已签名的值。正确。后修订。
#include <stdlib.h>
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define RAND_MAX_BITWIDTH (IMAX_BITS(RAND_MAX))
unsigned long rand_ul(void) {
  unsigned long r = 0;
  for (int i=0; i<IMAX_BITS(ULONG_MAX); i += RAND_MAX_BITWIDTH) {
    r <<= RAND_MAX_BITWIDTH;
    r |= rand();
  }
  return r;
}