引言
偶然看到一个加密问题,说要把若干个整数按二进制样式做成首尾衔接的环,然后要查找这个环中0和1的数目,还要确定某个二进制的片段在整个环里不重复。
我没有想得太细,只是想起了很早以前模拟大整数运算器时采取的一种原始方法—就是把数字转换为字符串,利用字符串拼接,人工地模拟二进制的位运算。于是想着做一个能支持位移的字符串,便有了下面这个小东西。
当然,这个结构很不完善,一方面是支持的位数有限制,二是取值也还有一些障碍,权当一乐了。
示例代码
一、将uint转换为32位的二进制字符串的扩展类
简单地利用“与”运算,按位生成uint值对应的二进制字符串。Convert.ToString(int value, int base)可以支持2/8/10/16四种进制。
public static class UIntToBinString { public static string ToBinString(this uint value) { StringBuilder result = new StringBuilder(); for (int i = 0, mask = 1; i < 32; i++, mask <<= 1) { if ((value & mask) == mask) result.Insert(0, '1'); else result.Insert(0, '0'); } return result.ToString(); } }
二、对单个字符串实现位移的类
声明一个位移处理的委托ShiftHandler,方便之后的处理。
public class StringNode { private string _value; public string Value { get { return _value; } } public delegate void ShiftHandler(int bit, ref string segment); public ShiftHandler LeftShiftHandler; public ShiftHandler RightShiftHandler; private StringNode() { this.LoadDefaultHandler(); } public StringNode(string value) : this() { Debug.Assert(!string.IsNullOrEmpty(value), "Ctor does not accept empty or null string as para."); this._value = value; } private void LeftShift(int bit, ref string segment) { Debug.Assert(bit > 0, "para bit must be greater than zero."); Debug.Assert(!string.IsNullOrEmpty(segment), "para segment can not be empty or null."); Debug.Assert(bit == segment.Length, "length of para segment does not equals to bit."); string temp = this._value; this._value = temp.Substring(bit) + segment; segment = temp.Substring(0, bit); } private void RightShift(int bit, ref string segment) { Debug.Assert(bit > 0, "para bit must be greater than zero."); Debug.Assert(!string.IsNullOrEmpty(segment), "para segment can not be empty or null."); Debug.Assert(bit == segment.Length, "length of para segment does not equals to bit."); string temp = this._value; this._value = segment + temp.Substring(0, temp.Length - bit); segment = temp.Substring(temp.Length - bit); } public void LoadDefaultHandler() { this.LeftShiftHandler = new ShiftHandler(this.LeftShift); this.RightShiftHandler = new ShiftHandler(this.RightShift); } }
三、对前一个类StringNode的升级和再封装
把若干个字符串拼接起来,实现整体位移。
public class StringQueue : List<StringNode> { public void LeftShift(int bit) { Debug.Assert(bit > 0, "para bit must be greater than zero."); string temp = this[0].Value.Substring(0, bit); this.AttachChain(); this[0].LeftShiftHandler(bit, ref temp); this.DetachChain(); } public void RightShift(int bit) { Debug.Assert(bit > 0, "para bit must be greater than zero."); string temp = this[this.Count-1].Value; temp = temp.Substring(temp.Length - bit); this.AttachChain(); this[0].RightShiftHandler(bit, ref temp); this.DetachChain(); } private void AttachChain() { for (int i = 1; i < this.Count; i++) { this[0].LeftShiftHandler += this[i].LeftShiftHandler; this[0].RightShiftHandler += this[i].RightShiftHandler; } } private void DetachChain() { this[0].LoadDefaultHandler(); } public void DisplayValue() { Console.ForegroundColor = ConsoleColor.Yellow; foreach (StringNode node in this) Console.Write(node.Value); Console.WriteLine(); Console.ForegroundColor = ConsoleColor.White; } }
四、主程序示例
static void Main(string[] args) { uint[] array = new uint[] { 1315, 34135, 133813, 80761 }; StringQueue queue = new StringQueue(); foreach (uint value in array) queue.Add(new StringNode(value.ToBinString())); Console.WriteLine("原始值"); queue.DisplayValue(); Console.WriteLine("右移6位"); queue.RightShift(6); queue.DisplayValue(); Console.WriteLine("左移11位"); queue.LeftShift(11); queue.DisplayValue(); Console.ReadLine(); }
五、运行结果
原始值 00000000000000000000101001000110000000000000000 10000101010101110000000000000010000101010110101 00000000000000010011101101111001 右移6位 11001000000000000000000000101001000110000000000 00000010000101010101110000000000000100000101010 11010100000000000000010011101101 左移11位 00000000000000010100111001000000000000000010000 10101111001000000000000001000001101010001100000 00000000001001110110101011100000