我正在开发一个在 C# 中反转整数的函数,同时也处理负数。我想出了以下实现:
public void Reverse(int x)
{
const int INT_MAX = 2147483647;
const int INT_MIN = -2147483648;
bool isNegative = false;
if (x < 0)
{
isNegative = true;
x = Math.Abs(x);
}
long reversed = 0;
while (x != 0)
{
int lastDigit = x % 10;
reversed = reversed * 10 + lastDigit;
x = x / 10;
}
if (isNegative)
{
reversed = -reversed;
}
if (reversed > INT_MAX || reversed < INT_MIN)
{
Console.WriteLine(0);
}
Console.WriteLine ((int)reversed);
}
该函数对于正数似乎工作得很好,但是当我传入 INT_MIN(即 -2147483648)时,我遇到了意外的行为。 Math.Abs(x) 调用会抛出 System.OverflowException:对二进制补码数的最小值取反是无效的。
我的目的是在反转输入整数之前将其转换为其绝对值,以便该函数可以正确处理负数。然而,在这个实现中,取 INT_MIN 的绝对值似乎会导致溢出。
有人可以建议我如何处理负数的反转,同时避免溢出吗?
您可以执行以下操作:使用
long
作为中间值或 忽略负值。
模运算符
%
对于负数(在左侧操作数中)工作得很好,并返回负结果。对于你想要做的事情来说,这大大简化了事情。您可以忽略它们,而不是尝试显式处理负数。
这大大简化了方法:
static long Reverse(int x)
{
long result = 0;
while (x != 0)
{
result = result * 10 + x % 10;
x /= 10;
}
return result;
}
对于
int.MinValue
(你的 INT_MIN
),顺序如下:
x | x % 10 | 结果 |
---|---|---|
-2147483648 | -8 | -8 |
-214748364 | -4 | -84 |
-21474836 | -6 | -846 |
-2147483 | -3 | -8463 |
-214748 | -8 | -84638 |
-21474 | -4 | -846384 |
-2147 | -7 | -8463847 |
-214 | -4 | -84638474 |
-21 | -1 | -846384741 |
-2 | -2 | -8463847412 |
因为我喜欢简洁的代码,所以让我们使用
for
循环来减少行数:
static long Reverse(int x)
{
long result = 0;
for (; value != 0; value /= 10)
result = result * 10 + value % 10;
return result;
}
(是的,我也可以将主体放入循环增量中,但这更容易阅读。)