比特组范围在USHORT [英] Set Range of Bits in a ushort
问题描述
可以说我有,我想设置位USHORT值1到4包容性(假设0是LSB和15是MSB)。
在C ++中,你可以定义映射出特定位的结构:
结构KibblesNBits
{
无符号短整型TheStart:1;
无符号短整型TheMeat:4;
无符号短整型TheRest:11;
}
然后,你可以分配一个值直接'TheMeat。我希望做在C#中类似的东西。理想情况下,我想这看起来像这样一个函数,定义:
公共ModValue SetRange< ModValue,RangeValue>(ModValue valueToMod,诠释了startIndex,诠释endIndex的,RangeValue rangeValueToAssign)
它还需要的Valide该rangeValueToAssign不超过最大尺寸(假设值是无符号从0到最大)。因此,如果范围是从1至4个,这是4位,范围是从0到15。如果它是这些限制之外,抛出异常。
我没有发现在BitConverter类,可以做一些这样的事。尽我所能想到用manaul移位运算符的。有没有更好的方式来做到这一点?
编辑:非通用版本可能是这个样子:
公共静态USHORT SetRange(USHORT valueToMod,诠释了startIndex,诠释endIndex的,USHORT rangeValueToAssign)
{
//确定最大值
USHORT MAX_VALUE = Convert.ToUInt16(Math.Pow(2.0,(endIndex的 - 的startIndex)+ 1.0) - 1);
如果(rangeValueToAssign> MAX_VALUE)抛出新的异常(价值大对于范围);
//移值,并把它添加到一部开拓创新(设置范围的影响?)
USHORT value_to_add =(USHORT)(rangeValueToAssign<<的startIndex);
回报(USHORT)(valueToMod + value_to_add);
}
其中:
USHORT new_val = SetRange(120,1,2,3);
将导致'new_val'设定为126
公共静态INT SetRange(INT NUM,从INT,INT到,int值)
{
如果(从℃,从||>到||到大于= 32)抛出新的ArgumentException(自/至无效);
如果(价值> =(2';<(至 - 从))及及(至 - 来自以下; 31))抛出新的ArgumentException(值过大);
返回NUM和放大器; 〜(((2';&下;对) - 1) - ((1 <<;&下;从) - 1))| (价值&LT;&LT;从);
}
没有for循环或Math.Pow(这是令人惊讶的速度慢,比正弦/余弦等方法要慢)。
至于通用 - 对不起,这是行不通的。目前在C#(或.NET)号也基本类型,所以这是根本不可能的。它看起来像你试图用像C ++模板函数++仿制药 - 不要被类似的外观所迷惑;它们是完全不同的。
如果你必须有不同的类型,我建议重载代替。
公共静态INT SetRange(INT NUM,从INT,INT到,int值)
{
如果(从℃,从||&gt;到||到大于= 32)抛出新的ArgumentException(自/至无效);
如果(价值&GT; =(2';&LT;(至 - 从))及及(至 - 来自以下; 31))抛出新的ArgumentException(值过大);
返回NUM和放大器; 〜(((2';&下;对) - 1) - ((1 <<;&下;从) - 1))| (价值&LT;&LT;从);
}公共静态USHORT SetRange(USHORT NUM,从int,int值,USHORT值)
{
如果(从℃,从||&gt;到||到大于= 16)抛出新的ArgumentException(自/至无效);
如果(价值&GT; =(2';&LT;(至 - 从)))抛出新的ArgumentException(值过大);
返回(USHORT)(民&放大器;〜(((2';&下;对) - 1) - ((1 <<;&下;从) - 1))|(值下;&下;从));
}
不过,在C#中它可能(如果你需要一个或长)是更地道,只是总是使用int类型。
Lets say I have a ushort value that I would like to set bits 1 to 4 inclusive (assuming 0 is the LSB and 15 is the MSB).
In C++ you could define a struct that mapped out specific bits:
struct KibblesNBits
{
unsigned short int TheStart: 1;
unsigned short int TheMeat: 4;
unsigned short int TheRest: 11;
}
Then you could assign a value to 'TheMeat' directly. I'm looking to do something similar in C#. Ideally, I would like a funcion definition that looked like this:
public ModValue SetRange<ModValue, RangeValue>(ModValue valueToMod, int startIndex, int endIndex, RangeValue rangeValueToAssign)
It would also need to valide that the rangeValueToAssign does not exceed the maximum size (assuming values are unsigned from 0 to max). So if the range is from 1 to 4, this is 4 bits, range would be from 0 to 15. If it is outside these limits, throw an exception.
I didnt find anything in the BitConverter class that could do something like this. Best I could think of was using manaul shift operators. Is there a better way to do this?
Edit: A non generic version might look something like this:
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);
}
Where:
ushort new_val = SetRange(120, 1, 2, 3);
would result in 'new_val' being set to 126.
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);
}
No for-loops or Math.Pow (which is amazingly slow, way slower than Sin/Cos etc).
As for generic - sorry, that won't work. There is no base type for numbers in C# (or .NET), so this is simply impossible. It looks like you're trying to use generics like template functions in C++ - don't be fooled by the similar looks; they are completely different.
If you must have different types, I'd suggest overloads instead.
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));
}
However, in C# it might be more idiomatic to just always use int (or long if you need that).
这篇关于比特组范围在USHORT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!