Почему BigInteger.ToString ("x") предшествует 0 для значений между Sign.MaxValue (эксклюзивно) и unsigned.MaxValue (включительно)? - PullRequest
3 голосов
/ 06 июня 2011

Примеры (звездочки рядом со странным поведением):

    [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"));
    }
  • Есть ли причина для этого?
  • Как бы удалить этот дополнительный ноль?Могу ли я просто проверить, имеет ли строка ноль в начале и, если да, удалить его?Есть ли какие-нибудь угловые случаи, о которых стоит подумать?

Ответы [ 6 ]

3 голосов
/ 06 июня 2011

Без начального нуля число может выглядеть так, как если бы оно было отрицательным числом того же числа битов в дополнении до двух. Установка начального нуля гарантирует, что старший бит не установлен, поэтому его нельзя интерпретировать как отрицательное число.

Продолжите и удалите первый символ, если это ноль, если только это не единственный символ в строке.

1 голос
/ 06 июня 2011

Положительные значения IMO должны включать ведущий ноль, и я думаю, именно поэтому вы видите их в своих результатах.

Чтобы избежать, возможно, вы могли бы указать конкретное форматирование для вывода

0 голосов
/ 06 июня 2011

Может быть интересно отметить, что byte[], возвращаемый методом ToByteArray, также содержит начальный нулевой байт в ваших примерах.

Итак, чтобы ответить на ваш вопрос буквально, ваши примеры отформатированыс начальным нулем, потому что байтовый массив, представляющий число, содержит начальный ноль, и именно этот массив выводится в шестнадцатеричном формате.

0 голосов
/ 06 июня 2011

Без причины? !

Возможно, это просто причуды!Помните, библиотеки базовых классов были разработаны разработчиками, т.е. людьми!Вы можете ожидать, что в них закрадывается странный причуд.

0 голосов
/ 06 июня 2011

Кажется, что BigInteger со спецификатором формата x хочет записать байт за раз.

См. Этот пример:

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, чтобы обойти эту проблему.

0 голосов
/ 06 июня 2011

С моей стороны, я не уверен, почему это сделано, но, как вы упомянули, преобразование в строку, а затем удаление начального нуля должно помочь.

...