为什么BigInteger.ToString(“x”)在带符号之间的值前面加一个0.MaxValue(独占)和无符号.M

本文关键字:一个 MaxValue 无符号 独占 前面 ToString BigInteger 为什么 之间 带符号 | 更新日期: 2023-09-27 17:58:30

示例(奇数行为旁边的星号):

    [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"));
    }
  • 这是有原因的吗
  • 我该如何删除这个多余的零?我可以检查字符串的开头是否为零吗?如果是,请删除它?有什么角落的案子需要考虑吗

为什么BigInteger.ToString(“x”)在带符号之间的值前面加一个0.MaxValue(独占)和无符号.M

如果没有前导零,该数字可能看起来像是2的补码中相同位数的负数。放一个前导零可以确保高位不被设置,因此它不可能被解释为负数。

如果第一个字符是零,则继续删除它,除非它是字符串中唯一的字符。

在我的部分中,我不确定为什么要这样做,但正如您所提到的,转换为字符串,然后删除前导零应该就可以了。

IMO正值应该包括一个前导零,我相信这就是你在输出中看到这些值的原因。

为了避免这种情况,您可以为输出指定特定的格式

似乎带有x格式说明符的BigInteger希望一次写出一个字节。

参见此示例:

writeHex(new BigInteger(15));

0f

因此,在开始时可以随意移除任何填充的'0'

private static void writeHex(BigInteger value)
{
    Console.WriteLine(value.ToString("x").TrimStart('0'));
}

这是有原因的吗?

他们以这种方式实现它的一个很好的理由是,它仍然是正确的,并且可能在用于实现ToString(避免分支)的紧密循环中表现更好。

从反射器来看,实现方式如下:

StringBuilder builder = new StringBuilder();
byte[] buffer = value.ToByteArray();
// ... A bunch of pre-amble for special cases here,
// though obviously not including the high byte being < 0x10.  Then:
while (index > -1)
{
    builder.Append(buffer[index--].ToString(str, info));
}

编辑

本提出了一个很好的观点。你给出的一些例子输出了奇数个半字节,所以我想实现方式很奇怪:)

您仍然可以使用string.TrimStart函数来解决这个问题。

没有原因

也许这只是一句俏皮话!请记住,基类库是由开发人员,即人类开发的!你可以期待奇怪的俏皮话悄悄进入他们。

值得注意的是,在您的示例案例中,方法ToByteArray返回的byte[]也包含一个前导零字节。

所以,为了从字面上回答你的问题,你的例子是用前导零格式化的,因为表示数字的字节数组包含前导零,而这个数组是十六进制的。

相关文章: