BigInteger.Parse() 大量读取时遇到问题
BigInteger.Parse() trouble reading in large numbers
目前我正在尝试完成这个挑战 (http://cryptopals.com/sets/1/challenges/1),但我在用 C# 完成任务时遇到了一些问题。我似乎无法将数字解析为一个大整数。
因此代码如下所示:
string output = "";
BigInteger hexValue = BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6");
output = Convert.ToBase64String(hexValue.ToByteArray());
Console.WriteLine(hexValue);
Console.WriteLine(output);
Console.ReadKey();
return "";
目前我遇到的问题是当我运行程序失败并出现错误
System.FormatException: 'The value could not be parsed.' and I am not entirely sure why.
那么,将字符串中的大整数转换为 BigInt 的合适方法是什么?
问题是输入的不是十进制而是十六进制,所以需要额外传递一个参数进行解析:
BigInteger number = BigInteger.Parse(
hexString,
NumberStyles.AllowHexSpecifier);
使用NumberStyles.HexNumber
:
BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6",
NumberStyles.HexNumber,
CultureInfo.InvariantCulture);
如果您的数字应该始终为正数,请在您的字符串中添加一个前导零。
初始问题
BigInteger.Parse
方法期望值是十进制的,而不是十六进制的。您可以 "fix" 通过传入 NumberStyles.HexNumber
.
使用BigInteger
的更大问题
如果您只是想将一串十六进制数字转换为字节,我会完全避免使用 BigInteger
。一方面,例如,如果原始字节数组以零开头,您最终可能会遇到问题。零不会在生成的字节数组中。 (示例输入:“0001”——你想输出两个字节,但在说服它解析十六进制后你只会得到一个。)
即使您没有丢失任何信息,您从BigInteger.ToByteArray()
收到的byte[]
也可能不是您所期望的。例如,考虑这段代码,它只是将数据转换为 byte[]
并通过 BitConverter
:
转换回十六进制
BigInteger bigInt = BigInteger.Parse("1234567890ABCDEF", NumberStyles.HexNumber);
byte[] bytes = bigInt.ToByteArray();
Console.WriteLine(BitConverter.ToString(bytes));
它的输出是 "EF-CD-AB-90-78-56-34-12" - 因为 BigInteger.ToByteArray
returns little-endian 顺序中的数据:
The individual bytes in the array returned by this method appear in little-endian order. That is, the lower-order bytes of the value precede the higher-order bytes.
这不是你想要的 - 因为它意味着原始字符串的 last 部分是字节数组的 first 部分,等等
完全避免BigInteger
相反,将数据 直接 解析为字节数组,如 this question, or this one 或其他各种形式。我不会在这里重现代码,但它很简单,根据您是要创建简单的源代码还是要创建高效的程序,有不同的选项。
关于转化的一般建议
一般来说,避免数据的中间表示是个好主意,除非您绝对确信您不会在此过程中丢失信息 - 正如您在这里所做的那样。在将结果转换为 base64 之前将十六进制字符串转换为字节数组很好,因为这不是有损转换。
所以您的转化是:
String
(十六进制)到 BigInteger
:有损(在前导 0 很重要的情况下,就像在这种情况下一样)
BigInteger
到 byte[]
:无损
byte[]
到 String
(base64):无损
我推荐:
String
(十六进制)到 byte[]
:无损(假设您有偶数个字节要转换,这通常是一个合理的假设)
byte[]
到 String
(base64):无损
目前我正在尝试完成这个挑战 (http://cryptopals.com/sets/1/challenges/1),但我在用 C# 完成任务时遇到了一些问题。我似乎无法将数字解析为一个大整数。
因此代码如下所示:
string output = "";
BigInteger hexValue = BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6");
output = Convert.ToBase64String(hexValue.ToByteArray());
Console.WriteLine(hexValue);
Console.WriteLine(output);
Console.ReadKey();
return "";
目前我遇到的问题是当我运行程序失败并出现错误
System.FormatException: 'The value could not be parsed.' and I am not entirely sure why.
那么,将字符串中的大整数转换为 BigInt 的合适方法是什么?
问题是输入的不是十进制而是十六进制,所以需要额外传递一个参数进行解析:
BigInteger number = BigInteger.Parse(
hexString,
NumberStyles.AllowHexSpecifier);
使用NumberStyles.HexNumber
:
BigInteger.Parse("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6",
NumberStyles.HexNumber,
CultureInfo.InvariantCulture);
如果您的数字应该始终为正数,请在您的字符串中添加一个前导零。
初始问题
BigInteger.Parse
方法期望值是十进制的,而不是十六进制的。您可以 "fix" 通过传入 NumberStyles.HexNumber
.
使用BigInteger
的更大问题
如果您只是想将一串十六进制数字转换为字节,我会完全避免使用 BigInteger
。一方面,例如,如果原始字节数组以零开头,您最终可能会遇到问题。零不会在生成的字节数组中。 (示例输入:“0001”——你想输出两个字节,但在说服它解析十六进制后你只会得到一个。)
即使您没有丢失任何信息,您从BigInteger.ToByteArray()
收到的byte[]
也可能不是您所期望的。例如,考虑这段代码,它只是将数据转换为 byte[]
并通过 BitConverter
:
BigInteger bigInt = BigInteger.Parse("1234567890ABCDEF", NumberStyles.HexNumber);
byte[] bytes = bigInt.ToByteArray();
Console.WriteLine(BitConverter.ToString(bytes));
它的输出是 "EF-CD-AB-90-78-56-34-12" - 因为 BigInteger.ToByteArray
returns little-endian 顺序中的数据:
The individual bytes in the array returned by this method appear in little-endian order. That is, the lower-order bytes of the value precede the higher-order bytes.
这不是你想要的 - 因为它意味着原始字符串的 last 部分是字节数组的 first 部分,等等
完全避免BigInteger
相反,将数据 直接 解析为字节数组,如 this question, or this one 或其他各种形式。我不会在这里重现代码,但它很简单,根据您是要创建简单的源代码还是要创建高效的程序,有不同的选项。
关于转化的一般建议
一般来说,避免数据的中间表示是个好主意,除非您绝对确信您不会在此过程中丢失信息 - 正如您在这里所做的那样。在将结果转换为 base64 之前将十六进制字符串转换为字节数组很好,因为这不是有损转换。
所以您的转化是:
String
(十六进制)到BigInteger
:有损(在前导 0 很重要的情况下,就像在这种情况下一样)BigInteger
到byte[]
:无损byte[]
到String
(base64):无损
我推荐:
String
(十六进制)到byte[]
:无损(假设您有偶数个字节要转换,这通常是一个合理的假设)byte[]
到String
(base64):无损