比特组范围在USHORT [英] Set Range of Bits in a ushort

查看:102
本文介绍了比特组范围在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆