为什么 BigInteger.ToString(“x”) 会为signed.MaxValue(不包括)和 unsigned.MaxValue(包括)之间的值添加 0?
示例(奇怪行为旁边的星号):
[Fact]
public void BigInteger_ToString_behavior_is_odd()
{
writeHex(new BigInteger(short.MaxValue)); // 7fff
writeHex(new BigInteger(short.MaxValue) + 1); // 08000 **
writeHex(new BigInteger(ushort.MaxValue)); // 0ffff **
writeHex(new BigInteger(ushort.MaxValue) + 1); // 10000
writeHex(new BigInteger(int.MaxValue)); // 7fffffff
writeHex(new BigInteger(int.MaxValue) + 1); // 080000000 **
writeHex(new BigInteger(uint.MaxValue)); // 0ffffffff **
writeHex(new BigInteger(uint.MaxValue) + 1); // 100000000
writeHex(new BigInteger(long.MaxValue)); // 7fffffffffffffff
writeHex(new BigInteger(long.MaxValue) + 1); // 08000000000000000 **
writeHex(new BigInteger(ulong.MaxValue)); // 0ffffffffffffffff **
writeHex(new BigInteger(ulong.MaxValue) + 1); // 10000000000000000
}
private static void writeHex(BigInteger value)
{
Console.WriteLine(value.ToString("x"));
}
- 这有原因吗?
- 我该如何删除这个多余的零?我可以检查字符串开头是否有零,如果是,则将其删除吗?有什么极端情况需要考虑吗?
Examples (asterisks next to odd behavior):
[Fact]
public void BigInteger_ToString_behavior_is_odd()
{
writeHex(new BigInteger(short.MaxValue)); // 7fff
writeHex(new BigInteger(short.MaxValue) + 1); // 08000 **
writeHex(new BigInteger(ushort.MaxValue)); // 0ffff **
writeHex(new BigInteger(ushort.MaxValue) + 1); // 10000
writeHex(new BigInteger(int.MaxValue)); // 7fffffff
writeHex(new BigInteger(int.MaxValue) + 1); // 080000000 **
writeHex(new BigInteger(uint.MaxValue)); // 0ffffffff **
writeHex(new BigInteger(uint.MaxValue) + 1); // 100000000
writeHex(new BigInteger(long.MaxValue)); // 7fffffffffffffff
writeHex(new BigInteger(long.MaxValue) + 1); // 08000000000000000 **
writeHex(new BigInteger(ulong.MaxValue)); // 0ffffffffffffffff **
writeHex(new BigInteger(ulong.MaxValue) + 1); // 10000000000000000
}
private static void writeHex(BigInteger value)
{
Console.WriteLine(value.ToString("x"));
}
- Is there a reason for this?
- How would I remove this extra zero? Can I just check if the string has a zero at the start and, if so, remove it? Any corner cases to think about?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果没有前导零,该数字可能看起来像是二进制补码中相同位数的负数。添加前导零可确保不设置高位,因此它不可能被解释为负数。
如果第一个字符为零,则继续删除它,除非它是字符串中的唯一字符。
Without a leading zero, the number may appear as though it is a negative number of the same number of bits in two's complement. Putting a leading zero ensures that the high bit isn't set, so it can't possibly be interpreted as a negative number.
Go ahead and remove the first character, if it's a zero, unless it's the only character in the string.
从我的角度来看,不确定为什么要这样做,但正如您提到的转换为字符串然后删除前导零应该可以解决问题。
From my part not sure why this is done, but as you mentioned converting to string and then removing leading zero should do the trick.
IMO 正值应包含前导零,我相信这就是您在输出中看到这些值的原因。
为了避免,您可以为输出指定特定的格式
IMO positive values should include a leading zero and i believe that is why you see those in your outputs.
To avoid maybe you could specify a specific formatting for the output
看起来带有
x
格式说明符的BigInteger
想要一次写出一个字节。看这个例子:
因此,请随意删除开头的任何填充的
'0'
:他们以这种方式实现它的一个很好的理由是它仍然是正确的,并且可能在他们用来实现
ToString
的紧密循环中表现更好(避免分支)。从反射器来看,实现如下所示:
编辑:
嗯,Ben 提出了一个很好的观点。您提供的其中一些示例输出了奇数个半字节,因此我猜其实现很奇怪:)
您仍然可以使用 string.TrimStart 函数来解决该问题。
It seems that
BigInteger
with thex
format specifier wants to write out a byte at a time.See this example:
As such, feel free to remove any padded
'0'
at the beginning:A good reason for them to implement it this way is that it is still correct, and probably performs better in the tight loop they use to implement
ToString
(avoiding branches).From reflector, the implementation looks like this:
Edit:
Well, Ben brought up a good point. Some of those examples you gave output an odd number of nibbles, so I guess the implementation is just quirky :)
You can still use the
string.TrimStart
function to get around that problem.没有理由吗?!
也许这只是一个怪癖!请记住,基类库是由开发人员(即人类)开发的!你可以预料到他们身上会出现一些奇怪的怪癖。
No reason?!
Perhaps this is simply just a quirck! Remember, the base class libraries were developed by developers, i.e. humans! You can expect the odd quirck to creep into them.
值得注意的是,在您的示例中,方法
ToByteArray
返回的byte[]
还包含前导零字节。因此,为了从字面上回答您的问题,您的示例采用前导零进行格式化,因为表示数字的字节数组包含前导零,并且该数组以十六进制形式输出。
It might be interesting to note that the
byte[]
returned by the methodToByteArray
also contains a leading zero byte in your example cases.So, to answer your question literally, your examples are formatted with a leading zero because the byte array representing the number contains a leading zero and it's that array that's spit out in hexadecimal.