【问题标题】:BigInteger.ToString("x") doesn't properly print negative hex numbersBigInteger.ToString("x") 不能正确打印负十六进制数
【发布时间】:2013-02-18 13:33:49
【问题描述】:

我需要将 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

【问题讨论】:

  • 假设一个 8 位数字并没有错。 -1 = 0xff,-128 = 0x80,-127 = 0x81,-126 如图所示

标签: c# .net tostring biginteger


【解决方案1】:

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

【讨论】:

  • 唯一的问题是如果v 等于int.MinValue,这将崩溃。
  • 其实应该不会崩溃,但是结果会出乎意料,因为-Int.MinValue == Int.MinValue。而且,是的......这不会是BigInteger 的问题。
  • @JimMischel 实际上,再想一想,使用整数也可以。对于Int32.MinValue,算法将打印-80000000,这是正确的,一点也不意外。如果您将其全部转换为 long,您将得到与 Int32.MinValue 完全相同的结果。
【解决方案2】:

对于 C#,数字的十六进制格式输出永远不会是负数。

这也适用于整数 - 例如,

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

输出

FFFFFC18

【讨论】:

  • 同样(指问题的值)((sbyte)(-126)).ToString("X") 给出"82"((short)(-126)).ToString("X") 给出"FF82"(-126).ToString("X") 给出"FFFFFF82",最后(-126L).ToString("X") 给出"FFFFFFFFFFFFFF82"。因此,对于固定宽度的整数类型,我们会根据需要用Fs 填充以表示负值。对于BigInteger,这将是Fs 的无限前缀,这是不可能的。所以这里我们只包含一个F,如果前导十六进制数字在07之间。
  • 而正值可能需要在其十六进制格式输出中以0 开头,如((BigInteger)11).ToString("X") 中必须给出"0B",而不仅仅是"B"
【解决方案3】:

十六进制不能为负数。所以使用 Math.Sign 和 Math.Abs​​ :

        int v = -126;
        Console.WriteLine("{0} => {1}", v, (Math.Sign(v) < 0 ? "-" : String.Empty) + Math.Abs(v).ToString("X"));

【讨论】:

    猜你喜欢
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    • 2013-03-31
    • 1970-01-01
    相关资源
    最近更新 更多