两个大数字C#之间的差异

时间:2016-08-01 15:18:28

标签: c# math difference integer-overflow

小数字

已解决此问题

我将总结所有人的答案:

Math.Abs(a - b)

当数字很大时,问题是 这会给出错误的答案(通过溢出)。更糟糕的是,如果(a - b) = Int32.MinValue然后Math.Abs因异常而崩溃(因为Int32.MaxValue = Int32.MinValue - 1):

  

发生了System.OverflowException   的HResult = 0x80131516
  消息= 否定二进制补码的最小值   的无效即可。
  来源= mscorlib程序
  StackTrace:at   System.Math.Abs​​(Int32值)的System.Math.Abs​​Helper(Int32值)

它的特殊性质导致难以重现的错误。

也许我错过了一些众所周知的库函数,但有没有办法安全地确定差异?

4 个答案:

答案 0 :(得分:3)

正如其他人所建议的那样,使用System.Numerics中定义的BigInteger(你必须在Visual Studio中包含命名空间) 然后你可以这样做:

BigInteger a = new BigInteger();
BigInteger b = new BigInteger();
// Assign values to a and b somewhere in here...
// Then just use included BigInteger.Abs method
BigInteger result = BigInteger.Abs(a - b);

Jeremy Thompson的答案仍然有效,但请注意BigInteger命名空间包含绝对值方法,因此不需要特殊逻辑。另外,Math.Abs​​需要一个小数,所以如果你试图传入一个BigInteger,它会让你感到悲伤。

请记住,使用BigIntegers时需要注意。如果你有一个非常大的数字,C#将尝试为它分配内存,你可能会遇到内存不足的异常。另一方面,BigIntegers很棒,因为分配给它们的内存量随着数量的增加而动态变化。

查看微软参考资料,了解更多信息:https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx

答案 1 :(得分:1)

BigInteger是在.Net 4.0中引入的。

在.Net Framework的较低版本中有一些开源实现,但是你应该明智地使用标准。

如果Math.Abs仍然让你感到悲伤,你可以自己实现这个功能;如果数字是负的(a-b <0),只需修剪负符号使其无符号。

另外,你尝试过使用双打吗?他们拥有更大的价值观。

答案 2 :(得分:1)

问题是,你想如何保持两个大数字之间的差异?例如,如果您正在计算两个有符号长整数(64位)整数之间的差异,并且差异不适合有符号长整数,那么您打算如何存储它?

long    a = +(1 << 62) + 1000;
long    b = -(1 << 62);

long dif = a - b;    // Overflow, bit truncation

ab之间的差异大于64位,所以当它存储到一个长整数时,它的高位被截断,你得到一个奇怪的值dif

换句话说,您不能将给定宽度的有符号整数值之间的所有可能差异存储到相同宽度的有符号整数中。(您只能存储所有可能值的一半;另一半需要额外的一点。)

您的选择是使用更宽的类型来保持差异(如果您已经使用最宽的long整数类型,它将不会帮助您),或者使用不同的算法类型。如果您需要至少64个有符号的精度位,您可能需要使用BigInteger

答案 3 :(得分:0)

这是您可能感兴趣的替代方案,但非常符合特定int大小的范围。此示例使用Int32,并使用按位运算符来完成差异,然后使用绝对值。这个实现可以容忍你的场景,其中a-b等于min int值,它自然地返回min int值(你可以做的其他事情不多,而不会将事物转换为更大的数据类型)。我不认为这和使用BigInteger一样好,但如果没有别的话,玩它很有趣:

    static int diff(int a, int b)
    {
        int xorResult = (a ^ b);
        int diff = (a & xorResult) - (b & xorResult);
        return (diff + (diff >> 31)) ^ (diff >> 31);
    }

以下是我运行该行为的一些案例:

        Console.WriteLine(diff(13, 14)); // 1
        Console.WriteLine(diff(11, 9)); // 2
        Console.WriteLine(diff(5002000, 2346728)); // 2655272
        Console.WriteLine(diff(int.MinValue, 0)); // Should be 2147483648, but int data type can't go that large. Actual result will be -2147483648.