两个大数之间的区别C#
Difference between two large numbers C#
已经有小数字这个问题的解决方案:
- 此处:Difference between 2 numbers
- 此处:C# function to find the delta of two numbers
- 此处:How can I find the difference between 2 values in C#?
我会总结一下所有的答案:
Math.Abs(a - b)
问题是 当数字很大时 这会给出错误的答案(通过溢出)。更糟糕的是,如果 (a - b) = Int32.MinValue
然后 Math.Abs
崩溃并出现异常(因为 Int32.MaxValue = Int32.MinValue - 1
):
System.OverflowException occurred
HResult=0x80131516
Message=Negating the minimum value of a twos complement number is
invalid.
Source=mscorlib
StackTrace: at
System.Math.AbsHelper(Int32 value) at System.Math.Abs(Int32 value)
其特殊性质导致难以重现错误。
也许我遗漏了一些众所周知的库函数,但是有什么方法可以安全地确定差异吗?
.Net 4.0 中引入了 BigInteger。
在较低版本的 .Net Framework 中有一些开源实现可用,但是您最好采用标准。
如果 Math.Abs
仍然让您感到悲伤,您可以自己实现该功能;如果数字是负数 (a - b < 0) 简单地 trim 负号所以它是无符号的。
另外,你试过双打吗?他们拥有更大的价值。
按照其他人的建议,使用 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 很棒,因为分配给它们的内存量会随着数字变大而动态变化。
在此处查看 Microsoft 参考以获取更多信息:https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx
问题来了,你想怎么保存两个大数的差?例如,如果您正在计算两个有符号长整数(64 位)整数之间的差异,并且该差异不适合有符号长整数,您打算如何存储它?
long a = +(1 << 62) + 1000;
long b = -(1 << 62);
long dif = a - b; // Overflow, bit truncation
a
和 b
的区别是宽度大于 64 位,所以当它存储为一个长整数时,它的高位被截断,并且你得到一个奇怪的值 dif
.
换句话说,您无法将给定宽度的有符号整数值之间的所有可能差异存储到相同宽度的有符号整数中。(您只能存储所有值的一半可能的值;另一半需要额外的一点。)
您的选择是使用更宽的类型来保持差异(如果您已经在使用最宽的 long
整数类型,这对您没有帮助),或者使用不同的算术类型。如果您需要至少 64 位带符号的精度,您可能需要使用 BigInteger
.
这里有一个您可能感兴趣的替代方法,但它非常适合特定的 int 大小。本例使用Int32,使用位运算符先求差再求绝对值。此实现是 tole运行t 你的场景,其中 a - b 等于最小 int 值,它自然 returns 最小 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.
已经有小数字这个问题的解决方案:
- 此处:Difference between 2 numbers
- 此处:C# function to find the delta of two numbers
- 此处:How can I find the difference between 2 values in C#?
我会总结一下所有的答案:
Math.Abs(a - b)
问题是 当数字很大时 这会给出错误的答案(通过溢出)。更糟糕的是,如果 (a - b) = Int32.MinValue
然后 Math.Abs
崩溃并出现异常(因为 Int32.MaxValue = Int32.MinValue - 1
):
System.OverflowException occurred
HResult=0x80131516
Message=Negating the minimum value of a twos complement number is invalid.
Source=mscorlib
StackTrace: at System.Math.AbsHelper(Int32 value) at System.Math.Abs(Int32 value)
其特殊性质导致难以重现错误。
也许我遗漏了一些众所周知的库函数,但是有什么方法可以安全地确定差异吗?
.Net 4.0 中引入了 BigInteger。
在较低版本的 .Net Framework 中有一些开源实现可用,但是您最好采用标准。
如果 Math.Abs
仍然让您感到悲伤,您可以自己实现该功能;如果数字是负数 (a - b < 0) 简单地 trim 负号所以它是无符号的。
另外,你试过双打吗?他们拥有更大的价值。
按照其他人的建议,使用 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 很棒,因为分配给它们的内存量会随着数字变大而动态变化。
在此处查看 Microsoft 参考以获取更多信息:https://msdn.microsoft.com/en-us/library/system.numerics.biginteger(v=vs.110).aspx
问题来了,你想怎么保存两个大数的差?例如,如果您正在计算两个有符号长整数(64 位)整数之间的差异,并且该差异不适合有符号长整数,您打算如何存储它?
long a = +(1 << 62) + 1000;
long b = -(1 << 62);
long dif = a - b; // Overflow, bit truncation
a
和 b
的区别是宽度大于 64 位,所以当它存储为一个长整数时,它的高位被截断,并且你得到一个奇怪的值 dif
.
换句话说,您无法将给定宽度的有符号整数值之间的所有可能差异存储到相同宽度的有符号整数中。(您只能存储所有值的一半可能的值;另一半需要额外的一点。)
您的选择是使用更宽的类型来保持差异(如果您已经在使用最宽的 long
整数类型,这对您没有帮助),或者使用不同的算术类型。如果您需要至少 64 位带符号的精度,您可能需要使用 BigInteger
.
这里有一个您可能感兴趣的替代方法,但它非常适合特定的 int 大小。本例使用Int32,使用位运算符先求差再求绝对值。此实现是 tole运行t 你的场景,其中 a - b 等于最小 int 值,它自然 returns 最小 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.