Set bit range in user

Suppose I have a ushort value that I would like to set bits from 1 to 4 inclusive (assuming 0 is LSB and 15 is MSB).

In C ++, you can define a structure that maps specific bits:

struct KibblesNBits
{
   unsigned short int TheStart: 1;
   unsigned short int TheMeat:  4;
   unsigned short int TheRest: 11;
}

Then you can directly set the value to "TheMeat". I want to do something like this in C #. Ideally, I would like the funcion definition to look like this:

public ModValue SetRange<ModValue, RangeValue>(ModValue valueToMod, int startIndex, int endIndex, RangeValue rangeValueToAssign)

It would also be necessary to evaluate that rangeValueToAssign does not exceed the maximum size (provided that the unsigned values ​​are from 0 to max). Therefore, if the range is from 1 to 4, it is 4 bits, the range will be from 0 to 15. If it goes beyond these limits, throw an exception.

BitConverter, - . , . ?

: :

  public static ushort SetRange(ushort valueToMod, int startIndex, int endIndex, ushort rangeValueToAssign)
  {
     // Determine max value
     ushort max_value = Convert.ToUInt16(Math.Pow(2.0, (endIndex - startIndex) + 1.0) - 1);
     if(rangeValueToAssign > max_value) throw new Exception("Value To Large For Range");
     // Shift the value and add it to the orignal (effect of setting range?)
     ushort value_to_add = (ushort)(rangeValueToAssign << startIndex);
     return (ushort)(valueToMod + value_to_add);
  }

:

ushort new_val = SetRange(120, 1, 2, 3);

"new_val" 126.

+3
4
public static int SetRange(int num, int from, int to, int value)
{
    if (from < 0 || from > to || to >= 32) throw new ArgumentException("from/to are not valid");
    if (value >= (2 << (to - from)) && (to - from < 31)) throw new ArgumentException("value is too large");
    return num & ~(((2 << to) - 1) - ((1 << from) - 1)) | (value << from);
}

Math.Pow( , , Sin/Cos ..).

- , . # ( .NET), . , , ++, - ; .

, .

public static int SetRange(int num, int from, int to, int value)
{
    if (from < 0 || from > to || to >= 32) throw new ArgumentException("from/to are not valid");
    if (value >= (2 << (to - from)) && (to - from < 31)) throw new ArgumentException("value is too large");
    return num & ~(((2 << to) - 1) - ((1 << from) - 1)) | (value << from);
}

public static ushort SetRange(ushort num, int from, int to, ushort value)
{
    if (from < 0 || from > to || to >= 16) throw new ArgumentException("from/to are not valid");
    if (value >= (2 << (to - from))) throw new ArgumentException("value is too large");
    return (ushort) (num & ~(((2 << to) - 1) - ((1 << from) - 1)) | (value << from));
}

# int ( , ).

+2

, BitVector32 BitArray . # ( ), , . .

uint/int/ulong/long - .

0

- ( ), .

The only thing that comes to my mind is the old BitArray from .NET 1.1. But you can only manipulate individual bits, not bits.

So no.

0
source

Here is the fix for your update:

  public static ushort SetRange(ushort valueToMod, int startIndex, int endIndex, ushort rangeValueToAssign)
  {
     // Determine max value
     ushort max_value = Convert.ToUInt16(Math.Pow(2.0, (endIndex - startIndex) + 1.0) - 1);
     if(rangeValueToAssign > max_value) throw new Exception("Value To Large For Range");
     // Clear our bits where we want to "Set" the value for
     for( int i=startIndex; i<endIndex; i++ )
         valueToMod &= ~(1<<i);
     // Shift the value and add it to the orignal (effect of setting range?)
     ushort value_to_add = (ushort)(rangeValueToAssign << startIndex);
     return (ushort)(valueToMod + value_to_add);
  }
-1
source

Source: https://habr.com/ru/post/1732375/


All Articles