如何在C/ c++中随机翻转二进制位

How to random flip binary bit of char in C/C++

本文关键字:随机 翻转 二进制 c++      更新时间:2023-10-16

如果我有一个字符数组A,我用它来存储十六进制

A = "0A F5 6D 02"   size=11

这个字符数组的二进制表示为:

00001010 11110101 01101101 00000010  

我想问是否有任何函数可以随机翻转位?

即:
如果参数为5

00001010 11110101 01101101 00000010   
-->
10001110 11110001 01101001 00100010  

将随机选择5位进行翻转。

我试图使这个十六进制数据二进制数据和使用位掩码方法来实现我的要求。然后把它变回妖术。我很好奇有没有什么方法可以更快地完成这项工作?

对不起,我的问题描述得不够清楚。简单地说,我有一些十六进制数据,我想模拟这些数据中的位误差。例如,如果我有5字节的十六进制数据:

"FF00FF00FF" 

二进制表示为

"1111111100000000111111110000000011111111" 

如果误码率为10%。然后我想让这40位有4位的误差。一个极端的随机结果:错误发生在前4位:

"0000111100000000111111110000000011111111" 

首先,找出这个位代表的是哪个字符:

参数是你要翻转的位

char *byteToWrite = &A[sizeof(A) - (param / 8) - 1];

这将给你一个指向该数组偏移量的char指针(-1表示0数组偏移量vs大小)

然后得到模数(或者更多位移位如果你觉得冒险)来找出这里的哪个位要翻转:

*byteToWrite ^= (1u << param % 8);

因此,A[10]的字节的参数为5,其第5位被切换。

  1. 将2^n的值存储在数组
  2. 生成随机数种子
  3. 循环x次(在本例中为5次)并执行data ^= stored_values[random_num]

或者将2^n个值存储在数组中,您可以进行一些位移到2的随机幂,如:

data ^= (1<<random%7)

反映第一个注释,您真的可以在函数中将这行写5次,并完全避免for循环的开销。

您有32位数字。您可以将这些位视为数字的一部分,并将该数字与一些随机的5位数字进行xor。

int count_1s(int )
{
  int m = 0x55555555;
  int r = (foo&m) + ((foo>>>1)&m);
  m = 0x33333333;
  r = (r&m) + ((r>>>2)&m);
  m = 0x0F0F0F0F;
  r = (r&m) + ((r>>>4)&m);
  m = 0x00FF00FF;
  r = (r&m) + ((r>>>8)&m);
  m = 0x0000FFFF;
  return r = (r&m) + ((r>>>16)&m);
}
void main()
{
   char input[] = "0A F5 6D 02";
   char data[4] = {};
   scanf("%2x %2x %2x %2x", &data[0], &data[1], &data[2], &data[3]);
   int *x = reinterpret_cast<int*>(data);
   int y = rand();
   while(count_1s(y) != 5)
   {
      y = rand(); // let's have this more random
   }
   *x ^= y;
   printf("%2x %2x %2x %2x" data[0], data[1], data[2], data[3]);
   return 0;
}

我认为没有理由将整个字符串来回转换为十六进制表法。只需从十六进制字符串中随机选择一个字符,将其转换为数字,更改位,然后转换回十六进制字符。

C:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main (void)
{
    char *hexToDec_lookup = "0123456789ABCDEF";
    char hexstr[] = "0A F5 6D 02";
    /* 0. make sure we're fairly random */
    srand(time(0));
    /* 1. loop 5 times .. */
    int i;
    for (i=0; i<5; i++)
    {
        /* 2. pick a random hex digit
              we know it's one out of 8, grouped per 2 */
        int hexdigit = rand() & 7;
        hexdigit += (hexdigit>>1);
        /* 3. convert the digit to binary */
        int hexvalue = hexstr[hexdigit] > '9' ? hexstr[hexdigit] - 'A'+10 : hexstr[hexdigit]-'0';
        /* 4. flip a random bit */
        hexvalue ^= 1 << (rand() & 3);
        /* 5. write it back into position */
        hexstr[hexdigit] = hexToDec_lookup[hexvalue];
        printf ("[%s]n", hexstr);
    }
    return 0;
}

可能甚至可以省略ascii转换步骤——在字符串中翻转一个位,检查它是否仍然是一个有效的十六进制数字,如果需要,调整

  1. 首先随机选择x个位置(每个位置由数组索引和位位置组成)。

  2. 现在如果你想把i从右翻转到位对于一个数字n。通过2nn的余数:

代码:

int divisor = (2,i);
int remainder = n % divisor;
int quotient = n / divisor;
remainder = (remainder == 0) ? 1 : 0; // flip the remainder or the i th bit from right. 
n = divisor * quotient + remainder;
  1. 对输入(5%8)取模8

  2. 0x80右移输入值(例如5)

  3. 将此值与(input/8)字符数组的第1个元素进行XOR。

代码:

void flip_bit(int bit)
{
    Array[bit/8]  ^= (0x80>>(bit%8));
}