本文讲述了C#在USHORT中设置比特范围!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:
假设我有一个ushort值,我想设置位1到4(假设0是LSB,15是MSB)。
在C ++中,您可以定义一个映射出特定位的结构:
struct KibblesNBits { unsigned short int TheStart: 1; unsigned short int TheMeat: 4; unsigned short int TheRest: 11; }
然后你可以直接为’TheMeat’赋值。 我想在C#中做类似的事情。 理想情况下,我想要一个看起来像这样的function定义:
public ModValue SetRange(ModValue valueToMod, int startIndex, int endIndex, RangeValue rangeValueToAssign)
还需要确定rangeValueToAssign不超过最大大小(假设值从0到最大值无符号)。 因此,如果范围是1到4,则为4位,范围将为0到15.如果超出这些限制,则抛出exception。
我没有在BitConverter类中找到任何可以执行此类操作的内容。 我能想到的最好的就是使用manaul移位运算符。 有一个更好的方法吗?
编辑:非通用版本可能如下所示:
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。
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); }
没有for循环或Math.Pow(这是非常慢,比Sin / Cos等慢)。
至于通用 - 抱歉,这是行不通的。 C#(或.NET)中的数字没有基类型,所以这根本不可能。 看起来你正试图在C ++中使用像模板函数这样的generics - 不要被类似的外观所迷惑; 他们是完全不同的。
如果你必须有不同的类型,我建议重载。
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)); }
但是,在C#中,总是使用int(或者如果你需要那么长)可能更惯用。
这里的固定类型答案帮助我按原始要求获得通用解决方案。 这是最终的代码(带有吸气剂奖励)。
/// Gets the bit array value from the specified range in a bit vector. /// The type of the bit vector. Must be of type . /// The bit vector. /// The zero-based start index of the bit range to get. /// The number of sequential bits to fetch starting at . /// The value of the requested bit range. public static T GetBits(T bits, byte startIdx, byte count) where T : IConvertible { if (startIdx >= (Marshal.SizeOf(typeof(T)) * 8)) throw new ArgumentOutOfRangeException(nameof(startIdx)); if (count + startIdx > (Marshal.SizeOf(typeof(T)) * 8)) throw new ArgumentOutOfRangeException(nameof(count)); return (T)Convert.ChangeType((bits.ToInt64(null) >> startIdx) & ((1 << count) - 1), typeof(T)); } /// Sets the bit values at the specified range in a bit vector. /// The type of the bit vector. Must be of type . /// The type of the value. Must be of type . /// The bit vector. /// The zero-based start index of the bit range to set. /// The number of sequential bits to set starting at . /// The value to set within the specified range of . public static void SetBits(ref T bits, byte startIdx, byte count, TValue value) where T : IConvertible where TValue : IConvertible { if (startIdx >= (Marshal.SizeOf(typeof(T)) * 8)) throw new ArgumentOutOfRangeException(nameof(startIdx)); if (count + startIdx > (Marshal.SizeOf(typeof(T)) * 8)) throw new ArgumentOutOfRangeException(nameof(count)); var val = value.ToInt64(null); if (val >= (1 << count)) throw new ArgumentOutOfRangeException(nameof(value)); bits = (T)Convert.ChangeType(bits.ToInt64(null) & ~(((1 << count) - 1) << startIdx) | (val << startIdx), typeof(T)); },>
如果您想要这种类型的访问,请考虑使用BitVector32或BitArray ,或熟悉按位算术。 您可以在C#中明确布局结构(导致联合),但我不认为这对您有利。 它主要针对互操作场景。
对于info,按位运算符主要在uint / int / ulong / long – 而不是较小的整数类型。
我不知道任何语言function(除了手动移位),这将实现这一目标。
我唯一想到的是来自.NET 1.1的旧BitArray 。 但是你只能操纵各个位,而不能操作位范围。
所以不行。
以下是您的更新修复:
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;>
更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。
想高效系统的学习Python编程语言,推荐大家关注一个微信公众号:Python编程学习圈。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Python入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!