我正在编写一个压缩非常大数字的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 ...
我可能会遗漏一些明显的东西,但我似乎无法找到一种安全的方法来计算Int64.MaxValue - signedInt64Var
的初始差异,因为这总是会产生一个值>= 0
并且可能产生一个超出Int64范围的值(如果signedInt64Var为负数)。
我是否需要使用按位运算符手动屏蔽符号位?
或者是否存在仅使用基本比较运算符以及某些有符号/无符号转换的解决方案?
我希望尽可能避免转换为十进制 - 高容量性能优先级。
答案 0 :(得分:2)
实际上非常简单,演员阵容已经足够,并且没有剩余的角落案例需要特别注意。
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);
}
这些溢出测试依赖于常规(无界)算法的不变量 - 如果它们失败,则发生溢出。
b
未签名,因此从不否定