如何随机化64位模式中的最低位

时间:2016-02-15 20:07:10

标签: c random bit-manipulation bit-shift

我有兴趣更多地了解位移和后续生成位操作背后的概念。下面是一些打印20个随机64位模式的代码。 “rand_bits”使用C标准rand()返回64位模式,除了最低位(随机化)之外全部为零。低随机化位的数量由函数的唯一参数提供。

   const int LINE_CNT = 20;

    void print_bin(uint64_t num, unsigned int bit_cnt);

    uint64_t rand_bits(unsigned int bit_cnt);

    int main(int argc, char *argv[]) {

        int i;

        srand(time(NULL));
        for(i = 0; i < LINE_CNT; i++) {
            uint64_t val64 = rand_bits(64);
            print_bin(val64, 64);
        }
    return EXIT_SUCCESS;
    }


    void print_bin(uint64_t num, unsigned int bit_cnt) {

        int top_bit_cnt;

        if(bit_cnt <= 0) return;
        if(bit_cnt > 64) bit_cnt = 64;

        top_bit_cnt = 64;
        while(top_bit_cnt > bit_cnt) {
            top_bit_cnt--;
            printf(" ");
        }

        while(bit_cnt > 0) {
            bit_cnt--;
            printf("%d", (num & ((uint64_t)1 << bit_cnt)) != 0);
        }
        printf("\n");

        return;
    }


    /*
     * Name: rand_bits
     * Function: Returns a 64 bit pattern with all zeros except for the
     *           lowest requested bits, which are randomized.  
     * Parameter, "bit_cnt":  How many of the lowest bits, including the
     *           lowest order bit (bit 0) to be randomized
     * Return: A 64 bit pattern with the low bit_cnt bits randomized.
     */
    uint64_t rand_bits(unsigned int bit_cnt) {


        printf("int bit_cnt:", bit_cnt);
        uint64_t result = rand();
        uint64_t result_1 = result>>5;
// uint64_t result_1 = result>>7;

//return result;
        return result_1;

    }

例如,如果使用24作为参数值调用函数,则可能返回a 64位模式,例如:

0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_​1101_0110_0101_1110_0111_1100

目前函数rand_bits可能会显示来自rand()函数的超过15个随机位,但这是NO保证。

我认为要获得40位,就像在示例中我可以右移位,但这似乎不是概念。这是否需要高阶位的位掩码或随机数发生器的mod计算?

有关如何以最低位(bit_cnt)随机化返回所有零位模式的任何建议吗?

更新:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>

const int LINE_CNT = 20;

uint64_t rand_bits( unsigned number_of_bits ){

    uint64_t r = 0;
    unsigned i;
    for(i = 0; i <= number_of_bits / 15; i++ ){
         r = (r << 15) | (rand() & 0x7fff ) ;
    }

    return r & ~(~0ull << number_of_bits) ;
}

void print_bin(uint64_t num, unsigned int bit_cnt) {

        int top_bit_cnt;

        if(bit_cnt <= 0) return;
        if(bit_cnt > 64) bit_cnt = 64;

        top_bit_cnt = 64;
        while(top_bit_cnt > bit_cnt) {
            top_bit_cnt--;
            printf(" ");
        }

        while(bit_cnt > 0) {
            bit_cnt--;
            printf("%d", (num & ((uint64_t)1 << bit_cnt)) != 0);
        }
        printf("\n");

        return;
    }


int main(void) {
int i;
/*      for(i = 0; i < 64; i++)
            print_bin(rand_bits(i),64);
        return EXIT_SUCCESS;
*/

        //I want to keep the code like this, but have the output shown in          //the links.
        srand(time(NULL));
        for(i = 0; i < LINE_CNT; i++) {
                uint64_t val64 = rand_bits(64);
                print_bin(val64, 64);
        }
return EXIT_SUCCESS;
}

当我将代码保持在我最初的方式时,输出全为0。有关如何使我的代码保持原来的方式的任何建议,并产生正好20行64位,最低位随机化?

3 个答案:

答案 0 :(得分:0)

uint64_t rand_bits(unsigned int number_of_bits) 
{
    uint64_t r = 0;
    int i;
    for(i = 0 ; i < number_of_bits/15 ; i++ )
    {
         r = (r<<15)|(rand()&32767u);
    }
    int remainder = number_of_bits-i*15;
    r = (r<<remainder)|(rand()&~(~0ull<<remainder));
    return r;
}

由于RAND_MAX保证提供15位,所以一次做1位是没有意义的。

答案 1 :(得分:0)

rand()int范围内生成[0 ...RAND_MAX]RAND_MAX至少为32767,当然比2的幂小1。

如此有效地循环几次,直到我们有bit_cnt个随机位。这个技巧是通过利用RAND_MAX可能大于32767来最小化循环计数。

#include <stdlib.h>

// Valid for 0 <= bit_cnt <= uintmax_t bit wdith
uintmax_t randomized_lowest_bits(unsigned bit_cnt) {
  // Create mask, same as maximum return value
  uintmax_t mask = 1;
  if (bit_cnt >= CHAR_BIT * sizeof(uintmax_t)) {
    mask = -1;
  } else {
    mask = (mask << bit_cnt) - 1;
  }
  uintmax_t limit = mask;
  uintmax_t x = 0;

  while (limit) {
    // x *= (RAND_MAX +1)
    // Done as below to prevent numeric overflow of `RAND_MAX + 1u` on rare machines.
    // Let the compiler optimize it, likely into a fixed count left shift
#if RAND_MAX == INT_MAX
    x = x * (RAND_MAX / 2 + 1) * 2;
#else
    x *= RAND_MAX + 1;
#endif

    // Bring in more bits
    x += rand();

    // Carefully divide by RAND_MAX + 1 with overflow safe guards
    // Again, let the compiler optimize the code, likely into a fixed count right shift
#if RAND_MAX == INT_MAX
    limit = (limit / (RAND_MAX / 2 + 1)) / 2;
#else
    limit /= RAND_MAX + 1;
#endif
  }
  return x & mask;
}

void testR(void) {
  for (int i = 0; i <= 64; i++) {
    printf("%jX\n", randomized_lowest_bits(i));
  }
}

输出

0
1
3
...
1192962917E96171
24833D39561F3B29
C3EC4ED846755A5B

答案 2 :(得分:0)

通过连接足够数量的15位随机序列,然后在this.http.get('lib/respApiTest.res') .subscribe(testReadme => this.testReadme = testReadme.text()); 不是15的完全倍数时屏蔽不需要的位:

number_of_bits