Convert Positive Integer to Negative and Vice Versa in Java – 在 Java 中将正整数转换为负整数,反之亦然

最后修改: 2023年 12月 3日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In Java programming, understanding how to manipulate integers is fundamental to writing robust and efficient code. One common operation is negating an integer.

在 Java 编程中,了解如何操作 整数是编写健壮高效代码的基础。一个常见的操作是否定整数。

In this tutorial, we’ll explore different approaches to negating an integer.

在本教程中,我们将探讨否定整数的不同方法。

2. Introduction to the Problem

2.问题介绍

Negating an integer involves changing its sign from positive to negative or vice versa. For example, given an int 42, after negating it, we expect to get -42 as the result.

对一个整数进行负运算,就是将其符号从正变为负,反之亦然。例如,给定一个 int 42,在对它进行否定运算后,我们期望得到的结果是-42。

We shouldn’t forget the number 0 is neither positive nor negative. Therefore, the result of negating 0 should be 0, too.

我们不应该忘记,数字 0 既不是正数,也不是负数。因此,否定 0 的结果也应该是 0。

In Java, this operation is straightforward, and we’ll see three different ways to achieve it. Additionally, we’ll discuss a corner case: integer overflow.

在 Java 中,这一操作非常简单,我们将看到实现这一操作的三种不同方法。此外,我们还将讨论一种极端情况:整数 溢出

For simplicity, we’ll use unit test assertions to verify the result of each approach.

为简单起见,我们将使用单元测试断言来验证每种方法的结果。

3. Using the Unary Minus Operator

3.使用一元减运算符

The most straightforward approach to negate an integer is using the unary minus operator (). It simply changes the sign of the given integer:

否定整数最直接的方法是使用 unary 减运算符 ()。它可以简单地改变给定整数的符号

int x = 42;
assertEquals(-42, -x);

int z = 0;
assertEquals(0, -z);

int n = -42;
assertEquals(42, -n);

As the test shows, we get the expected results by applying ‘‘ to the input integers.

正如测试所示,通过对输入的整数应用”“,我们得到了预期的结果。

4. Using the Bitwise Complement Operator

4.使用比特补码操作符

Another unconventional yet effective way to negate an integer is using the bitwise complement operator (~). This operator inverts the bits of the given integer, effectively creating the two’s complement:

另一种非常规但有效的否定整数的方法是使用 比特互补运算符 (~)。该运算符会反转给定整数的位,从而有效地创建 两位互补运算符

int number = 12;
int negative13 = ~number; // ~00001100 = 11110011 = -13

Therefore, given an integer x, ~x + 1 is the negation of x.

因此,给定整数 x, ~x + 1 是 x 的否定。

Next, let’s write a test to verify that:

接下来,让我们编写一个测试来验证这一点:

int x = 42;
assertEquals(-42, ~x + 1);

int z = 0;
assertEquals(0, ~z + 1);

int n = -42;
assertEquals(42, ~n + 1);

As we can see, ~x + 1 solves the problem.

我们可以看到,~x + 1 解决了问题。

5. Overflow Concerns With Integer.MIN_VALUE

5.Integer.MIN_VALUE 的溢出问题

We know Java’s integer type is a signed 32-bit type with a range from -2147483648 to 2147483647. If we negate Integer.MAX_VALUE, the result –2147483647 is still in the range. But, if we negate Integer.MIN_VALUE, we should get 2147483648, which is greater than Integer.MAX_VALUETherefore, in this edge case, an overflow error occurs.

我们知道 Java 的整数类型是带符号的 32 位类型,其范围从 -21474836482147483647. 如果我们否定 Integer.MAX_VALUE, 结果 –2147483647 仍然在范围内。但是,如果我们否定 Integer.MIN_VALUE, 我们应该得到 2147483648, 它大于 Integer.MAX_VALUE因此,在这种边缘情况下,会出现溢出错误。

Although the ‘-x‘ and ‘~x + 1‘ approaches are straightforward, we can only use them in our applications if we ensure overflow won’t happen. A few example scenarios where using them might be appropriate include:

虽然”-x“和”~x + 1“方法简单明了,但只有在确保不会发生溢出的情况下,我们才能在应用程序中使用它们。适合使用它们的几个示例场景包括:-x~x + 1

  • Calculating a soccer team’s goal difference in a tournament
  • Calculating an employee’s working hours in a month

However, if overflow might happen in our program, using these approaches is discouraged.

但是,如果我们的程序中可能出现溢出,则不鼓励使用这些方法。

Next, let’s explore why these two approaches result in an overflow error when using Integer.MIN_VALUE as the input.

接下来,让我们来探讨一下为什么使用 Integer.MIN_VALUE 作为输入时,这两种方法都会导致溢出错误。

5.1. -x With Integer.MIN_VALUE

5.1.-x With Integer.MIN_VALUE

First, let’s negate Integer.MIN_VALUE using the ‘‘ operator:

首先,让我们使用”“操作符否定 Integer.MIN_VALUE

int min = Integer.MIN_VALUE;
LOG.info("The value of '-min' is: " + -min);
 
assertTrue((-min) < 0);

This test passes, meaning we still have a negative result after negating an Integer.MIN_VALUE. We can further verify this from the output:

该测试通过,这意味着在否定 Integer.MIN_VALUE 之后,我们仍然得到了否定结果。我们可以从输出中进一步验证这一点:

The value of '-min' is: -2147483648

Therefore, the ‘-x’ approach returns the wrong result when an overflow occurs.

因此,当发生溢出时,‘-x’ 方法会返回错误的结果。

5.2. ~x + 1 With Integer.MIN_VALUE

5.2.~x + 1 使用 Integer.MIN_VALUE

Let’s run the same test using the ‘~x + 1′ approach:

让我们使用”~x + 1′ 方法 “进行同样的测试:

int min = Integer.MIN_VALUE;
int result = ~min + 1;
LOG.info("The value of '~min + 1' is: " + result);
 
assertFalse(result > 0);

We can see that this approach won’t give the expected result either when an overflow occurs. Let’s verify this further by checking the log output in the console:

我们可以看到,当发生溢出时,这种方法也不会得到预期的结果。让我们通过检查控制台中的日志输出来进一步验证这一点:

The value of '~min + 1' is: -2147483648

6. Using the Math.negateExact() Method

6.使用 Math.negateExact() 方法

For scenarios where dealing with Integer.MIN_VALUE is required,  the Math.negateExact() method provides a safe and precise way to negate an integer.

对于需要处理 Integer.MIN_VALUE 的情况,Math.negateExact() 方法提供了一种安全而精确的否定整数的方法。

First, Math.negateExact() works as expected in normal cases:

首先,Math.negateExact() 在一般情况下都能正常工作:

int x = 42;
assertEquals(-42, Math.negateExact(x));

int z = 0;
assertEquals(0, Math.negateExact(z));

int n = -42;
assertEquals(42, Math.negateExact(n));

Next, let’s see what comes out if the input is Integer.MIN_VALUE:

接下来,让我们看看如果输入是 Integer.MIN_VALUE 会产生什么结果:

int min = Integer.MIN_VALUE;
assertThrowsExactly(ArithmeticException.class, () -> Math.negateExact(min));

As the test shows, the Math.negateExact() method raises an ArithmeticException if an overflow occurs during the negation, allowing the developer to handle the error when it occurs.

如测试所示,如果在否定过程中发生溢出,Math.negateExact()方法将引发算术异常允许开发人员在错误发生时进行处理。

7. Conclusion

7.结论

In this article, we’ve explored three ways to negate an integer in Java.

在本文中,我们探讨了在 Java 中否定整数的三种方法。

-x‘ and ‘~x + 1‘ are straightforward solutions. However, if our program might try to negate Integer.MIN_VALUE, then using Math.negateExact() is the right choice.

-x‘和’~x + 1‘是直接的解决方案。但是,如果我们的程序可能会尝试否定 Integer.MIN_VALUE, 那么使用 Math.negateExact() 是正确的选择

As always, the complete source code for the examples is available over on GitHub.

与往常一样,这些示例的完整源代码可在 GitHub 上获取。