2013-03-04 3 views
3

Мне нужно распечатать BigInteger как отрицательное число, однако Hex-перегрузка ToString («X») неверна.BigInteger.ToString («x») неправильно печатает отрицательные шестнадцатеричные числа

 BigInteger be1 = new BigInteger(); 
     be1 = 0x7e; 
     Console.WriteLine(be1.ToString());  // 126 
     Console.WriteLine(be1.ToString("X")); // 7E 
     Console.WriteLine(be1.ToString("x")); // 7e 
     Console.WriteLine(); 
     be1 = BigInteger.Negate(be1); 
     Console.WriteLine(be1.ToString());  // -126 OK 
     Console.WriteLine(be1.ToString("X")); // 82 WRONG 
     Console.WriteLine(be1.ToString("x")); // 82 WRONG 

Я делаю что-то неправильно, как я могу это исправить?

(Для чего это стоит, что я делаю это так, я могу match the hex output here, illustrated as an C++ array)

+0

Это не совсем так, если принять 8-битное число. -1 = 0xff, -128 = 0x80, -127 = 0x81, -126, как показано – kenny

ответ

6

ToString печатает шестнадцатеричное целое, как если бы оно было без подписи. Чтобы напечатать шестнадцатеричный знак, отмените значение и префикс его знаком.

BigInteger v = new BigInteger(-10); 
string str = "-" + (-v).ToString("X"); // "-0A" 

В качестве метода расширения, он может работать так:

class Program 
{ 
    static void Main(string[] args) 
    { 
     BigInteger v = new BigInteger(-10); 
     Console.WriteLine(v.ToSignedHexString()); // Prints: "-0A" 
     Console.ReadLine(); 
    } 
} 

public static class BigIntegerExtensions 
{ 
    public static string ToSignedHexString(this BigInteger value) 
    { 
     if (value.Sign == -1) 
      return "-" + (-value).ToString("X"); 
     else 
      return value.ToString("X"); 
    } 
} 
+0

Единственная проблема в том, что это произойдет, если 'v' равно' int.MinValue'. –

+0

На самом деле, он не должен падать, но результаты будут неожиданными, потому что '-Int.MinValue == Int.MinValue'. И, да ... это не будет проблемой с «BigInteger». –

+0

@JimMischel На самом деле, со второй мыслью, с целыми числами он будет работать так же хорошо. Для 'Int32.MinValue' алгоритм будет печатать' -80000000', что является правильным и вовсе не неожиданным. Если бы вы все бросили на 'long', вы получили бы тот же результат для' Int32.MinValue'. – Virtlink

2

Шестнадцатиричный выходной формат для чисел никогда не негативна для C#.

Это относится и к Интс тоже - например,

int x = -1000; 
Console.WriteLine(x.ToString("X")); 

выходы

FFFFFC18 
+0

Также (со ссылкой на значение вопроса) '((sbyte) (- 126)) ToString (" X ")' дает '" 82 "' и '((short) (- 126)) ToString («X») 'дает' 'FF82" 'и' (-126) .ToString ("X") 'дает' "FFFFFF82" 'и, наконец,' (-126L) .ToString ("X") 'дает' "FFFFFFFFFFFFFF82" '. Таким образом, при использовании целочисленных типов с фиксированной шириной мы получаем «F's», если необходимо, чтобы обозначить отрицательное значение. Для 'BigInteger' это будет бесконечный префикс' F', который невозможен. Таким образом, здесь мы просто включаем 'F', если бы ведущая шестнадцатеричная цифра в противном случае находилась бы в интервале от 0 до 7. –

+0

И позитивным значениям может понадобиться ведущий '0' в их шестнадцатеричном форматировании, как в' ((BigInteger) 11) .ToString ("X") ', который должен давать' '0B" ', а не только' 'B" ' , –

1

гекс не может быть отрицательным. Поэтому используйте Math.Sign и Math.Abs:

 int v = -126; 
     Console.WriteLine("{0} => {1}", v, (Math.Sign(v) < 0 ? "-" : String.Empty) + Math.Abs(v).ToString("X")); 
Смежные вопросы