Question

How can I ensure that when changing a bit from a BitArray, the BitArray value remains in a range.

Example:

Given the range [-5.12, 5.12] and

a = 0100000000000000011000100100110111010010111100011010100111111100 ( = 2.048)

By changing a bit at a random position, I need to ensure that the new value remains in the given range.

Was it helpful?

Solution

I'm not 100% sure what you are doing and this answer assumes you are storing a as a 64-bit value (long) currently. The following code may help point you in the right direction.

const double minValue = -5.12;
const double maxValue = 5.12;

var initialValue = Convert.ToInt64("100000000000000011000100100110111010010111100011010100111111100", 2);
var changedValue = ChangeRandomBit(initialValue); // However you're doing this

var changedValueAsDouble = BitConverter.Int64BitsToDouble(initialValue);
if ((changedValueAsDouble < minValue) || (changedValueAsDouble > maxValue))
{
    // Do something
}

OTHER TIPS

It looks like double (64 bits and result has decimal point).

As you may know it has sign bit, exponent and fraction, so you can not change random bit and still have value in the range, with some exceptions:

  • sign bit can be changed without problem if your range is [-x;+x] (same x);
  • changing exponent or fraction will require to check new value range but:
  • changing exponent of fraction bit from 1 to 0 will make |a| less.

I don't know what you are trying to achieve, care to share? Perhaps you are trying to validate or correct something, then you may have a look at this.

Here's an extension method that undoes the set bit if the new value of the float is outside the given range (this is an example only, it relies on the BitArray holding a float with no checks, which is pretty horrible so just hack a solution out of this, incl changing to double):

static class Extension
{
    public static void SetFloat(this BitArray array, int index, bool value, float min, float max)
    {
        bool old = array.Get(index);
        array.Set(index, value);
        byte[] bytes = new byte[4];
        array.CopyTo(bytes, 0);
        float f = BitConverter.ToSingle(bytes, 0);
        if (f < min || f > max)
            array.Set(index, old);
    }
}

Example use:

static void Main(string[] args)
{
    float f = 2.1f;
    byte[] bytes = System.BitConverter.GetBytes(f);
    BitArray array = new BitArray(bytes);
    array.Set(20, true, -5.12f, 5.12f);
}

If you can actually limit your precision, then this would be a lot easier. For example given the range:

[-5.12, 5.12]

If I multiply 5.12 by 100, I get

[-512, 512]

And the integer 512 in binary is, of course:

1000000000

So now you know you can set any of the first 9 bits and you'll be < 512 if the 10th bit is 0. If you set the 10th bit, you will have to set all the other bits to 0. With a little extra effort, this can be extended to deal with 2's complement negative values too (although, I might be inclined just to convert them to positive values)

Now if you actually need to accommodate the 3 d.p. of 2.048, then you'll need to multiply all you values by 1000 instead and it will be a little more difficult because 5120 in binary is 1010000000000

You know you can do anything you want with everything except the most significant bit (MSB) if the MSB is 0. In this case, if the MSB is 1, but the next 2 bits are 0, you can do anything you want with the remaining bits.

The logic involved with dealing directly with the number in IEEE-754 floating point format is probably going to be torturous.

Or you could just go with the "mutate the value and then test it" approach, if it's out-of-range, go back and try again. Which might be suitable (in practice), but won't be guaranteed to exit.

A final thought, depending on exactly what you are doing, you might want to also look at Gray Codes. The idea of a Gray Code is to make it such that each value is only 1 bit flip apart. With naturally encoded binary, a flip of the MSB has orders of magnitude more impact on the final value than a flip of the LSB.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top