Updated with newer answer and better test
Let\'s say I have the number 382 which is 101111110.
How could I randomly turn a bit which is not 0 to
You can generalize this by using BitArray.
public static BitArray FlipRandomTrueBit(BitArray bits)
{
List trueBits = new List();
for (int i = 0; i < bits.Count; i++)
if (bits[i])
trueBits.Add(i);
if (trueBits.Count > 0)
{
int index = rnd.Next(0, trueBits.Count);
bits[trueBits[index]] = false;
}
return bits;
}
However then you will have to write helper functions for simple data types.
public static int FlipRandomTrueBit(int input)
{
BitArray bits = new BitArray(new int[] { input });
BitArray flipedBits = FlipRandomTrueBit(bits);
byte[] bytes = new byte[4];
flipedBits.CopyTo(bytes, 0);
int result = BitConverter.ToInt32(bytes, 0);
return result;
}
If your using a large bit array you could save memory by iterating twice.
public static void FlipRandomTrueBitLowMem(ref BitArray bits)
{
int trueBits = 0;
for (int i = 0; i < bits.Count; i++)
if (bits[i])
trueBits++;
if (trueBits > 0)
{
int flip = rnd.Next(0, trueBits);
for (int i = 0; i < bits.Count; i++)
{
if (bits[i])
{
if (flip == 0)
{
bits[i] = false;
break;
}
flip--;
}
}
}
}
Test Program.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace bitarray
{
class Program
{
private static Random rnd = new Random((int)DateTime.Now.Ticks);
public static BitArray FlipRandomTrueBit(BitArray bits)
{
List trueBits = new List();
for (int i = 0; i < bits.Count; i++)
if (bits[i])
trueBits.Add(i);
if (trueBits.Count > 0)
{
int index = rnd.Next(0, trueBits.Count);
bits[trueBits[index]] = false;
}
return bits;
}
public static int FlipRandomTrueBit(int input)
{
BitArray bits = new BitArray(new int[] { input });
BitArray flipedBits = FlipRandomTrueBit(bits);
byte[] bytes = new byte[4];
flipedBits.CopyTo(bytes, 0);
int result = BitConverter.ToInt32(bytes, 0);
return result;
}
static void Main(string[] args)
{
int test = 382;
for (int n = 0; n < 200; n++)
{
int result = FlipRandomTrueBit(test);
Console.WriteLine(result);
}
Console.ReadLine();
}
}
}