如何将十进制转换为十六进制和十六进制字符串的异或
How to convert decimal to hexadecimal and XOR of the hex string
我有一个字符串数组 (string[]
) 作为十进制数,如 0, 0, 4, 142
,我想做的是将该数组转换为十六进制数,如 0, 0, 4, 8e
并执行C# 中的 XOR,但我没有得到 预期的 XOR,
代码:
public CheckSumHelper(string[] array)
{
this._array = array.Select(x => Convert.ToInt64(x, 16)).ToArray();
}
public string GetCheckSum()
{
long xor = this._array.Aggregate((x, y) => x ^ y);
return xor.ToString("X");
}
Convert.ToInt64(string,int)
方法指定字符串输入的基数。您正在将“142”转换为 0x142,而不是 0x8e。
只需使用 Convert.ToInt64(string)
.
至于您可能遇到的 XOR 问题,请参阅此 post:xor with 3 values
根据您提供的数据和计算校验和的想法,我怀疑您实际需要做的是提供纵向冗余校验。最简单的方法是:
(SumOfAllData & 0xFF) ^ 0xFF + 1
翻转数字中的所有位并加 1 的行为也称为二进制补码。
示例代码:
private int CalcChecksum(int[] array)
{
int Sum = array.Aggregate(0, (total, value) => total += value);
return ((Sum & 0xFF) ^ 0xFF) + 1;
}
因为142
是一个十进制(不是十六进制)数字(你不把0x142 == 332
), 将 16
放入 Convert.ToInt64(...)
:
public static string GetCheckSum(string[] array) {
// TODO: validate array here (it must be not null, not empty etc.)
return array
.Select(item => Convert.ToInt64(item)) // initial number is decimal
.Aggregate((s, item) => s ^ item)
.ToString("X"); // we want final result being hexadecimal
}
所以你会得到 0 ^ 0 ^ 4 ^ 142 == 138 == 0x8A
。
编辑: 使用格式时让计算机解释发生了什么:
private static string GetCheckSumExplained(string test) {
string[] array = test.Split(',');
// Routine under test - GetCheckSum
string result = GetCheckSum(array);
// Convert string back to long in order to represent it as binary and decimal
long resultAsInt = Convert.ToInt64(result, 16);
string args = string.Join(Environment.NewLine, array
.Select(item => Convert.ToInt64(item))
.Select(item => $"{Convert.ToString(item, 2).PadLeft(8, '0')} : {item,3} : 0x{item.ToString("X2")}"));
return string.Join(Environment.NewLine,
args,
"---------------------",
$"{Convert.ToString(resultAsInt, 2).PadLeft(8, '0')} : {resultAsInt,3} : 0x{result.PadLeft(2, '0')}");
}
...
string test = "0,0,4,20,15,142,0,8,179,141,0, 8, 181, 141, 0,8";
Console.Write(GetCheckSumExplained(test));
结果:
00000000 : 0 : 0x00
00000000 : 0 : 0x00
00000100 : 4 : 0x04
00010100 : 20 : 0x14
00001111 : 15 : 0x0F
10001110 : 142 : 0x8E
00000000 : 0 : 0x00
00001000 : 8 : 0x08
10110011 : 179 : 0xB3
10001101 : 141 : 0x8D
00000000 : 0 : 0x00
00001000 : 8 : 0x08
10110101 : 181 : 0xB5
10001101 : 141 : 0x8D
00000000 : 0 : 0x00
00001000 : 8 : 0x08
---------------------
10011111 : 159 : 0x9F
所以我们有 9F
。如果您确定正确答案是 B1
,您应该检查您的数据 or/and 公式
编辑 2: 如果初始 string
看起来像(见评论)
00[=13=]e[=13=]$b3d[=13=]$b5d[=13=]
我们可以将 GetCheckSum
实现为
// Now we're working with item_1$Item_2$...$Item_N
public static string GetCheckSum(string value) {
// TODO: Validate string here
return value
.Split('$')
.Select(item => Convert.ToInt64(item, 16)) // 16 is required in this format
.Aggregate((s, item) => s ^ item)
.ToString("X");
}
...
string test = "00[=14=]e[=14=]$b3d[=14=]$b5d[=14=]";
// Let's have a look on the the array
Console.WriteLine(string.Join(", ", test
.Split('$')
.Select(item => Convert.ToInt64(item, 16))));
Console.Wrire(GetCheckSum(test));
结果:
0, 0, 4, 32, 21, 142, 0, 8, 179, 141, 0, 8, 181, 141, 0, 8
B1
我有一个字符串数组 (string[]
) 作为十进制数,如 0, 0, 4, 142
,我想做的是将该数组转换为十六进制数,如 0, 0, 4, 8e
并执行C# 中的 XOR,但我没有得到 预期的 XOR,
代码:
public CheckSumHelper(string[] array)
{
this._array = array.Select(x => Convert.ToInt64(x, 16)).ToArray();
}
public string GetCheckSum()
{
long xor = this._array.Aggregate((x, y) => x ^ y);
return xor.ToString("X");
}
Convert.ToInt64(string,int)
方法指定字符串输入的基数。您正在将“142”转换为 0x142,而不是 0x8e。
只需使用 Convert.ToInt64(string)
.
至于您可能遇到的 XOR 问题,请参阅此 post:xor with 3 values
根据您提供的数据和计算校验和的想法,我怀疑您实际需要做的是提供纵向冗余校验。最简单的方法是:
(SumOfAllData & 0xFF) ^ 0xFF + 1
翻转数字中的所有位并加 1 的行为也称为二进制补码。
示例代码:
private int CalcChecksum(int[] array)
{
int Sum = array.Aggregate(0, (total, value) => total += value);
return ((Sum & 0xFF) ^ 0xFF) + 1;
}
因为142
是一个十进制(不是十六进制)数字(你不把0x142 == 332
), 将 16
放入 Convert.ToInt64(...)
:
public static string GetCheckSum(string[] array) {
// TODO: validate array here (it must be not null, not empty etc.)
return array
.Select(item => Convert.ToInt64(item)) // initial number is decimal
.Aggregate((s, item) => s ^ item)
.ToString("X"); // we want final result being hexadecimal
}
所以你会得到 0 ^ 0 ^ 4 ^ 142 == 138 == 0x8A
。
编辑: 使用格式时让计算机解释发生了什么:
private static string GetCheckSumExplained(string test) {
string[] array = test.Split(',');
// Routine under test - GetCheckSum
string result = GetCheckSum(array);
// Convert string back to long in order to represent it as binary and decimal
long resultAsInt = Convert.ToInt64(result, 16);
string args = string.Join(Environment.NewLine, array
.Select(item => Convert.ToInt64(item))
.Select(item => $"{Convert.ToString(item, 2).PadLeft(8, '0')} : {item,3} : 0x{item.ToString("X2")}"));
return string.Join(Environment.NewLine,
args,
"---------------------",
$"{Convert.ToString(resultAsInt, 2).PadLeft(8, '0')} : {resultAsInt,3} : 0x{result.PadLeft(2, '0')}");
}
...
string test = "0,0,4,20,15,142,0,8,179,141,0, 8, 181, 141, 0,8";
Console.Write(GetCheckSumExplained(test));
结果:
00000000 : 0 : 0x00
00000000 : 0 : 0x00
00000100 : 4 : 0x04
00010100 : 20 : 0x14
00001111 : 15 : 0x0F
10001110 : 142 : 0x8E
00000000 : 0 : 0x00
00001000 : 8 : 0x08
10110011 : 179 : 0xB3
10001101 : 141 : 0x8D
00000000 : 0 : 0x00
00001000 : 8 : 0x08
10110101 : 181 : 0xB5
10001101 : 141 : 0x8D
00000000 : 0 : 0x00
00001000 : 8 : 0x08
---------------------
10011111 : 159 : 0x9F
所以我们有 9F
。如果您确定正确答案是 B1
,您应该检查您的数据 or/and 公式
编辑 2: 如果初始 string
看起来像(见评论)
00[=13=]e[=13=]$b3d[=13=]$b5d[=13=]
我们可以将 GetCheckSum
实现为
// Now we're working with item_1$Item_2$...$Item_N
public static string GetCheckSum(string value) {
// TODO: Validate string here
return value
.Split('$')
.Select(item => Convert.ToInt64(item, 16)) // 16 is required in this format
.Aggregate((s, item) => s ^ item)
.ToString("X");
}
...
string test = "00[=14=]e[=14=]$b3d[=14=]$b5d[=14=]";
// Let's have a look on the the array
Console.WriteLine(string.Join(", ", test
.Split('$')
.Select(item => Convert.ToInt64(item, 16))));
Console.Wrire(GetCheckSum(test));
结果:
0, 0, 4, 32, 21, 142, 0, 8, 179, 141, 0, 8, 181, 141, 0, 8
B1