.NET 8 x64中BigInteger.Parse十六进制转十进制负数问题求助
.NET 8 x64中BigInteger.Parse解析十六进制为负数的问题及解决方案
问题原因
BigInteger是.NET中的有符号任意精度整数类型,当使用NumberStyles.HexNumber解析十六进制字符串时,解析逻辑会将字符串视为有符号数的十六进制补码表示。如果十六进制字符串的最高位字符是8-F(对应二进制最高位为1),解析器会将其识别为负数,从而得到错误的负数值;而添加前导零后,最高位变为0(二进制最高位为0),就会被解析为正确的正数。
比如示例中的9F4F4108B0BC1F2E02662669A635B9C,最高位是9,二进制为1001,被解析为负数;添加前导零后最高位为0,解析结果正确。
严谨解决方案
方法1:通过字节数组构造无符号BigInteger(推荐)
利用BigInteger的构造函数,将十六进制字符串转为字节数组后,指定isUnsigned: true参数(.NET Core 2.1及以上支持),直接解析为无符号数:
public static BigInteger ParseHexAsUnsigned(string hexStr) { if (string.IsNullOrWhiteSpace(hexStr)) throw new ArgumentException("十六进制字符串不能为空", nameof(hexStr)); // 处理奇数长度的字符串,补前导零保证字节转换正确 if (hexStr.Length % 2 != 0) { hexStr = "0" + hexStr; } // 将十六进制字符串转为大端字节数组 byte[] bigEndianBytes = new byte[hexStr.Length / 2]; for (int i = 0; i < hexStr.Length; i += 2) { bigEndianBytes[i / 2] = Convert.ToByte(hexStr.Substring(i, 2), 16); } // BigInteger构造函数默认使用小端字节序,因此需要反转数组 Array.Reverse(bigEndianBytes); return new BigInteger(bigEndianBytes, isUnsigned: true); }
方法2:自动补前导零处理字符串
检测十六进制字符串的最高位,若为8-F则添加前导零,确保解析时被视为正数:
public static BigInteger ParseHexAsUnsigned(string hexStr) { if (string.IsNullOrWhiteSpace(hexStr)) throw new ArgumentException("十六进制字符串不能为空", nameof(hexStr)); // 若最高位是8-F,添加前导零 if ("89ABCDEFabcdef".IndexOf(hexStr[0]) != -1) { hexStr = "0" + hexStr; } return BigInteger.Parse(hexStr, System.Globalization.NumberStyles.HexNumber); }
验证示例
对于十六进制字符串D0752364CFB600E410619304BE135C,使用上述任一方法均可得到正确结果:1082373592684167505354120550330274652。
内容的提问来源于stack exchange,提问作者JRrelyea
相关产品推荐
相关产品推荐

