C# 什么';确定Int64变量和Int64.MaxValue之间差异的最佳方法是什么?
我正在编写一个x64应用程序,它可以处理非常大的数字 我正在处理一种情况,需要确定将UInt64添加到Int64是否安全C# 什么';确定Int64变量和Int64.MaxValue之间差异的最佳方法是什么?,c#,64-bit,unsigned,signed,unsigned-integer,C#,64 Bit,Unsigned,Signed,Unsigned Integer,我正在编写一个x64应用程序,它可以处理非常大的数字 我正在处理一种情况,需要确定将UInt64添加到Int64是否安全 // Error: Operator '<=' is ambiguous on operands of type 'ulong' and 'long' if (UNsignedUInt64Var <= Int64.MaxValue - signedInt64Var) signedInt64Var = (Int64)(((UInt64)signedInt64
// Error: Operator '<=' is ambiguous on operands of type 'ulong' and 'long'
if (UNsignedUInt64Var <= Int64.MaxValue - signedInt64Var)
signedInt64Var = (Int64)(((UInt64)signedInt64Var) + UNsignedUInt64Var); // Maybe works?
else
// ... move on to a different operation ... unrelated ...
//错误:运算符'=0
,可能会产生超出Int64范围的值(如果SignedEnt64Var为负值)
我是否需要使用逐位运算符手动屏蔽符号位
或者有没有只使用基本比较运算符和一些有符号/无符号强制转换的解决方案
如果可能的话,我希望避免转换为十进制-高容量性能优先级。这实际上非常简单,强制转换就足够了,并且没有需要特别注意的剩余角案例
unchecked {
UInt64 n1 = (UInt64) Int64.MaxValue; // this is in range
UInt64 n2 = (UInt64) signedInt64Var; // this may wrap-around, if value is negative
UInt64 result = n1 - n2; // this is correct, because it
// wraps around in exactly the same cases that n2 did
}
然而,这闻起来像是一个XY问题。解决您的原始任务
我需要确定将UInt64添加到Int64是否安全
我会做这个手术,测试你的结果是否有效。在C++中,您必须事先测试溢出是否会发生,因为有符号整数溢出是未定义的行为。在C#中没有这种担心
Int64 a;
UInt64 b;
unchecked {
UInt64 uresult = b + (UInt64)a;
bool unsigned_add_was_safe = (uresult < b) == (a < 0);
Int64 sresult = a + (Int64)b;
bool signed_add_was_safe = (sresult >= a);
}
int64a;
UInt64 b;
未经检查{
UInt64 uresult=b+(UInt64)a;
bool unsigned_add_was_safe=(uresult=a);
}
这些溢出测试依赖于传统(无界)算法的不变量——如果它们失败,则发生溢出
- 当且仅当另一个操作数为负时,求和小于一个操作数
是无符号的,因此从不为负b
unchecked {
UInt64 n1 = (UInt64) Int64.MaxValue; // this is in range
UInt64 n2 = (UInt64) signedInt64Var; // this may wrap-around, if value is negative
UInt64 result = n1 - n2; // this is correct, because it
// wraps around in exactly the same cases that n2 did
}
然而,这闻起来像是一个XY问题。解决您的原始任务
我需要确定将UInt64添加到Int64是否安全
我会做这个手术,测试你的结果是否有效。在C++中,您必须事先测试溢出是否会发生,因为有符号整数溢出是未定义的行为。在C#中没有这种担心
Int64 a;
UInt64 b;
unchecked {
UInt64 uresult = b + (UInt64)a;
bool unsigned_add_was_safe = (uresult < b) == (a < 0);
Int64 sresult = a + (Int64)b;
bool signed_add_was_safe = (sresult >= a);
}
int64a;
UInt64 b;
未经检查{
UInt64 uresult=b+(UInt64)a;
bool unsigned_add_was_safe=(uresult=a);
}
这些溢出测试依赖于传统(无界)算法的不变量——如果它们失败,则发生溢出
- 当且仅当另一个操作数为负时,求和小于一个操作数
是无符号的,因此从不为负b
public static class Test {
public static Int64 add_if_in_range(Int64 basevalue, UInt64 newvalue) {
if (basevalue < 0 & (newvalue >= (UInt64)Int64.MaxValue) ) {
UInt64 ubase = (UInt64)(-basevalue);
return checked((Int64)(newvalue-ubase));
} else {
return checked(basevalue + (Int64)newvalue);
}
}
}
void Main()
{
// Some Test Cases:
Int64 l; UInt64 ul;
l = Int64.MaxValue; ul = 100; // result causes overflow of Int64
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MaxValue - 101; ul = 100; // result should be +9223372036854775806
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MaxValue/2; ul = (UInt64)Int64.MaxValue/2; // result should be +9223372036854775806
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MinValue; ul = 100; // result should be -9223372036854775708
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MinValue; ul = UInt64.MaxValue; // result should be +9223372036854775807
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MinValue; ul = UInt64.MaxValue-100; // result should be +9223372036854775807
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MinValue + 1; ul = UInt64.MaxValue; // result causes overflow of Int64
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
}
公共静态类测试{
公共静态Int64在\u范围内添加\u(Int64 basevalue,UInt64 newvalue){
if(basevalue<0&(newvalue>=(UInt64)Int64.MaxValue)){
UInt64-ubase=(UInt64)(-basevalue);
返回检查((Int64)(newvalue-ubase));
}否则{
返回选中(basevalue+(Int64)newvalue);
}
}
}
void Main()
{
//一些测试用例:
Int64 l;UInt64 ul;
l=Int64.MaxValue;ul=100;//结果导致Int64溢出
试一试{
控制台写入线(如果在(l,ul)范围内,则添加测试);
}捕获(溢出例外){
WriteLine(“添加将导致溢出”);
}
l=Int64.MaxValue-101;ul=100;//结果应为+9223372036854775806
试一试{
控制台写入线(如果在(l,ul)范围内,则添加测试);
}捕获(溢出例外){
WriteLine(“添加将导致溢出”);
}
l=Int64.MaxValue/2;ul=(UInt64)Int64.MaxValue/2;//结果应为+9223372036854775806
试一试{
控制台写入线(如果在(l,ul)范围内,则添加测试);
}捕获(溢出例外){
WriteLine(“添加将导致溢出”);
}
l=Int64.MinValue;ul=100;//结果应为-9223372036854775708
试一试{
控制台写入线(如果在(l,ul)范围内,则添加测试);
}捕获(溢出例外){
WriteLine(“添加将导致溢出”);
}
l=Int64.MinValue;ul=UInt64.MaxValue;//结果应为+9223372036854775807
试一试{
控制台写入线(如果在(l,ul)范围内,则添加测试);
}捕获(溢出例外){
WriteLine(“添加将导致溢出”);
}
l=Int64.MinValue;ul=UInt64.MaxValue-100;//结果应为+9223372036854775807
试一试{
控制台写入线(如果在(l,ul)范围内,则添加测试);
}捕获(溢出例外){
WriteLine(“添加将导致溢出”);
}
l=Int64.MinValue+1;ul=UInt64.MaxValue;//结果导致Int64溢出
试一试{
控制台写入线(如果在(l,ul)范围内,则添加测试);
}捕获(溢出例外){
WriteLine(“添加将导致溢出”);
}
}
使用关键字,我有一种不同的方法。我假设无符号long可能大于有符号long的最大正值,只要结果符合Int64的范围
下面是add_if_in_range()函数和几个检查其返回值的测试用例:
public static class Test {
public static Int64 add_if_in_range(Int64 basevalue, UInt64 newvalue) {
if (basevalue < 0 & (newvalue >= (UInt64)Int64.MaxValue) ) {
UInt64 ubase = (UInt64)(-basevalue);
return checked((Int64)(newvalue-ubase));
} else {
return checked(basevalue + (Int64)newvalue);
}
}
}
void Main()
{
// Some Test Cases:
Int64 l; UInt64 ul;
l = Int64.MaxValue; ul = 100; // result causes overflow of Int64
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MaxValue - 101; ul = 100; // result should be +9223372036854775806
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MaxValue/2; ul = (UInt64)Int64.MaxValue/2; // result should be +9223372036854775806
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MinValue; ul = 100; // result should be -9223372036854775708
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MinValue; ul = UInt64.MaxValue; // result should be +9223372036854775807
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MinValue; ul = UInt64.MaxValue-100; // result should be +9223372036854775807
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
l = Int64.MinValue + 1; ul = UInt64.MaxValue; // result causes overflow of Int64
try {
Console.WriteLine(Test.add_if_in_range(l, ul));
} catch (OverflowException) {
Console.WriteLine("Adding would cause an overflow");
}
}
公共静态类测试{
公共静态Int64在\u范围内添加\u(Int64 basevalue,UInt64 newvalue){
if(basevalue<0&(newvalue>=(UInt64)Int64.MaxValue)){
UInt64-ubase=(UInt64)(-basevalue);
返回检查((Int64)(newvalue-ubase));
}否则{
返回选中(basevalue+(Int64)newvalue);
}