byte 到unsigned BigInteger?
动机:为了在Code128C中制作条形码,我想将哈希值(MD5 / SHA1等)转换为十进制整数。 为简单起见,我更喜欢所有得到的(大)数字为正数。
我能够在C#中将byte []转换为BigInteger …
从我到目前为止的样本:
byte[] data; byte[] result; BigInteger biResult; result = shaM.ComputeHash(data); biResult = new BigInteger(result);
但是(这里生锈的CS)我更正确的是,字节数组总是可以用两种方式解释:A:作为有符号数B:作为无符号数
是否可以从C#中的byte []创建一个UNSIGNED BigInteger?
我应该简单地在字节[]的前面加一个0x00(零字节)吗?
编辑:感谢AakashM,Jon和Adam Robinson,在我需要的时候添加零字节。
编辑2:我应该做的主要是阅读BigInteger(byte [])构造函数的详细文档,然后我会看到有关如何通过附加零字节限制为正数的部分。
BigInteger
构造函数的备注表明,如果在调用构造函数之前将00
字节附加到数组的末尾,则可以确保从byte[]
创建的任何BigInteger
都是无符号的。
注意: BigInteger
构造函数要求数组采用little-endian顺序。 如果您希望生成的BigInteger
具有特定值,请记住这一点。
但是(这里生锈的CS)我更正确的是,字节数组总是可以用两种方式解释:A:作为有符号数B:作为无符号数
更正确的是,所有数字(由于存储在计算机中)基本上是一系列字节,这是字节数组。 说字节数组总是可以解释为特定数字类型的有符号或无符号版本,因为并非所有数字类型都有签名和无符号版本。 浮点类型通常只有签名版本(没有udouble
或ufloat
),并且在这个特定实例中,没有未签名的BigInteger
版本。
所以,换句话说,不,这是不可能的,但由于BigInteger
可以代表一个任意大的整数值,你不会因为它被签名而失去任何范围。
至于你的第二个问题,你需要将0x00
附加到数组的结尾 ,因为BigInteger
构造函数以little-endian字节顺序解析值。
检查相关BigInteger
构造函数的文档 ,我们看到:
值数组中的各个字节应采用小端顺序,从最低位字节到最高位字节
[…]
构造函数期望字节数组中的正值使用符号和幅度表示,而负值则使用2的补码表示。 换句话说,如果设置了值中最高位字节的最高位,则生成的BigInteger值为负 。 根据字节数组的来源,这可能会导致正值被误解为负值。
[…]
要防止将正值误解为负值,可以在数组末尾添加零字节值。
正如其他答案所指出的那样,您应该在数组的末尾添加一个00字节,以确保生成的BigInteger为正数。
根据BigInteger结构(System.Numerics)MSDN文档
防止BigInteger(Byte [])构造函数将负值的二进制补码表示与正值的符号和幅度表示混淆,正值通常是字节数组中最后一个字节的最高位set应包含一个值为0的附加字节。
这是代码:
byte[] byteArray; // ... var bigInteger = new BigInteger(byteArray.Concat(new byte[] { 0 }).ToArray());
另一种方法是使用您的字节数组创建一个BigInteger
,然后使用Abs
(相当于Math.Abs
)使其成为绝对值:
var bi = new BigInteger(result); var biPositive = BigInteger.Abs(bi1);
从技术上讲,如果bi
是负数,你只需要使用Abs
(例如,如果bi.Sign == -1
)