增加字节数组中的字符
Increment char in byte array
我正在用以下内容预填充一个字节数组:
private static byte[] idBuffer = ASCIIEncoding.Default.GetBytes("A" + DateTime.Now.ToString("yy") + DateTime.Now.DayOfYear + "0000001");
字节数组中的“0000001”部分是我的 ID 部分,我想在每次调用 "Increment" 方法时用 ASCII 字符 0-1A-S 递增。
例如,增量序列样本为:
000000S
...
00000S0
00000S1
...
00000SS
...
0000S00
...
0000S99
0000S9A
等等
我在想出正确的 algorithm/state 机器来正确递增字符时遇到一些问题。
现在我预填一个字符 table:
private static byte[] charCodes = new byte[] { 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 80, 81, 82, 83};
以及我为此在状态机上的粗略尝试,但它只让我获得了第二名:
if (idBuffer[bufPosition] < 83)
{
idBuffer[bufPosition] = charCodes[charCodePosition];
charCodePosition++;
}
else
{
if (idBuffer[bufPosition - 1] == 48)
{
for (int i = bufPosition; i < idBuffer.Length; i++)
idBuffer[i] = 48;
idBuffer[bufPosition - 1] = charCodes[charCodePosition2];
charCodePosition2++;
}
else
{
charCodePosition2++;
idBuffer[bufPosition - 1] = charCodes[charCodePosition2];
}
charCodePosition = 0;
}
我确信有一种我想不到的更优雅的方法来做到这一点 - 理想情况下,如果有人知道如何使用不安全的方法来做到这一点 code/pointers,那就更好了!
其实很简单:
- 从最后一个元素开始。
- 加一个。
- 如果您现在有
'0'+10
(58),请将其调整为 'A'
(65)。
- 如果你有除
'T'
以外的任何东西(懒得查ASCII码)你就完了。
- 调整为
'0'
(48)。
- 向左移动一个元素并从第 2 步开始重复。
基于,事实上你想要很酷的(假设目标更喜欢unsafe
)代码和固定大小的数字你可以将整个代码展开到简单的状态机中:
{number-to-add, char} -> {incremented char, carry}
'A'-'C' 的近似代码为 0,1,3。如果表合并为一个表(即将 char 和索引合并为单个 uint
带有位移的值)
,可能会稍微简化
char[2,256] incrementedChar = new char[2,256]{
{...64 0..., 'A', 'B', 'C', more 0 }, // A+0 = A,
{...64 0..., 'B', 'C', 'A', more 0 }};// A+1 = B, .., C+1 = A+carry
int[2,256] carryTable = new int[2,256]{
{...64 0..., 0, 0, 0, more 0 }, // adding 0 never carry
{...64 0..., 0, 0, 1, more 0 }};// carry when adding 1 to `C`
var chars = new[] {'A','A', 'A', 'C'};
int carry = 1; // adding 1 to the last digit
char current;
// unrolled loop from end to start. Adjust indexes if it is not in the beginning.
current = incrementedChar[carry, chars[3]];
carry = carryTable[carry, chars[3]];
chars[3] = current;
current = incrementedChar[carry, chars[2]];
carry = carryTable[carry, chars[2]];
chars[2] = current;
current = incrementedChar[carry, chars[1]];
carry = carryTable[carry, chars[1]];
chars[1] = current;
current = incrementedChar[carry, chars[0]];
carry = carryTable[carry, chars[0]];
chars[0] = current;
我正在用以下内容预填充一个字节数组:
private static byte[] idBuffer = ASCIIEncoding.Default.GetBytes("A" + DateTime.Now.ToString("yy") + DateTime.Now.DayOfYear + "0000001");
字节数组中的“0000001”部分是我的 ID 部分,我想在每次调用 "Increment" 方法时用 ASCII 字符 0-1A-S 递增。
例如,增量序列样本为:
000000S
...
00000S0
00000S1
...
00000SS
...
0000S00
...
0000S99
0000S9A
等等
我在想出正确的 algorithm/state 机器来正确递增字符时遇到一些问题。
现在我预填一个字符 table:
private static byte[] charCodes = new byte[] { 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 80, 81, 82, 83};
以及我为此在状态机上的粗略尝试,但它只让我获得了第二名:
if (idBuffer[bufPosition] < 83)
{
idBuffer[bufPosition] = charCodes[charCodePosition];
charCodePosition++;
}
else
{
if (idBuffer[bufPosition - 1] == 48)
{
for (int i = bufPosition; i < idBuffer.Length; i++)
idBuffer[i] = 48;
idBuffer[bufPosition - 1] = charCodes[charCodePosition2];
charCodePosition2++;
}
else
{
charCodePosition2++;
idBuffer[bufPosition - 1] = charCodes[charCodePosition2];
}
charCodePosition = 0;
}
我确信有一种我想不到的更优雅的方法来做到这一点 - 理想情况下,如果有人知道如何使用不安全的方法来做到这一点 code/pointers,那就更好了!
其实很简单:
- 从最后一个元素开始。
- 加一个。
- 如果您现在有
'0'+10
(58),请将其调整为'A'
(65)。 - 如果你有除
'T'
以外的任何东西(懒得查ASCII码)你就完了。 - 调整为
'0'
(48)。 - 向左移动一个元素并从第 2 步开始重复。
基于unsafe
)代码和固定大小的数字你可以将整个代码展开到简单的状态机中:
{number-to-add, char} -> {incremented char, carry}
'A'-'C' 的近似代码为 0,1,3。如果表合并为一个表(即将 char 和索引合并为单个 uint
带有位移的值)
char[2,256] incrementedChar = new char[2,256]{
{...64 0..., 'A', 'B', 'C', more 0 }, // A+0 = A,
{...64 0..., 'B', 'C', 'A', more 0 }};// A+1 = B, .., C+1 = A+carry
int[2,256] carryTable = new int[2,256]{
{...64 0..., 0, 0, 0, more 0 }, // adding 0 never carry
{...64 0..., 0, 0, 1, more 0 }};// carry when adding 1 to `C`
var chars = new[] {'A','A', 'A', 'C'};
int carry = 1; // adding 1 to the last digit
char current;
// unrolled loop from end to start. Adjust indexes if it is not in the beginning.
current = incrementedChar[carry, chars[3]];
carry = carryTable[carry, chars[3]];
chars[3] = current;
current = incrementedChar[carry, chars[2]];
carry = carryTable[carry, chars[2]];
chars[2] = current;
current = incrementedChar[carry, chars[1]];
carry = carryTable[carry, chars[1]];
chars[1] = current;
current = incrementedChar[carry, chars[0]];
carry = carryTable[carry, chars[0]];
chars[0] = current;