page contents

C#在USHORT中设置比特范围

本文讲述了C#在USHORT中设置比特范围!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

attachments-2022-10-9nJ7ikBL633e370e41598.png

本文讲述了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)); },>

如果您想要这种类型的访问,请考虑使用BitVector32BitArray ,或熟悉按位算术。 您可以在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入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2022-05-rLS4AIF8628ee5f3b7e12.jpg


  • 发表于 2022-10-06 10:02
  • 阅读 ( 348 )
  • 分类:C/C++开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. Pack 1131 文章
  3. 小柒 1046 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章