Why does BigInteger.ToString(“x”) prepend a 0 for

2020-03-24 04:03发布

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?

标签: c# biginteger
6条回答
女痞
2楼-- · 2020-03-24 04:41

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.

查看更多
来,给爷笑一个
3楼-- · 2020-03-24 04:43

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.

查看更多
何必那么认真
4楼-- · 2020-03-24 04:44

It seems that BigInteger with the x format specifier wants to write out a byte at a time.

See this example:

writeHex(new BigInteger(15));

0f

As such, feel free to remove any padded '0' at the beginning:

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

Is there a reason for this?

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:

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));
}

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.

查看更多
该账号已被封号
5楼-- · 2020-03-24 04:46

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

查看更多
欢心
6楼-- · 2020-03-24 05:00

It might be interesting to note that the byte[] returned by the method ToByteArray 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.

查看更多
smile是对你的礼貌
7楼-- · 2020-03-24 05:01

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.

查看更多
登录 后发表回答