C# 什么';确定Int64变量和Int64.MaxValue之间差异的最佳方法是什么?

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

我正在编写一个x64应用程序,它可以处理非常大的数字

我正在处理一种情况,需要确定将UInt64添加到Int64是否安全

// 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
    是无符号的,因此从不为负
使用关键字,我有一种不同的方法。我假设无符号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);
}       
}
}
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);
}