为什么对正数进行加一操作会得到一个负数?(Java)

huangapple go评论62阅读模式
英文:

Why does an increment by positive one return a negative? (Java)

问题

以下是翻译好的部分:

package calculations;

import java.util.ArrayList;

public class PrimeNumbers {
    public static void main(String[] args) {
        
         //声明要使用的变量...
         ArrayList<Integer> listOfPrimes = new ArrayList<Integer>();
         listOfPrimes.add(2);
         int numOfPrimesToList = 10;
         int possiblePrimeCounter  = 0;
         
         /* 我们从数字 2 开始测试,增加直到我们列出的质数列表等于
          * 我们想要列出的质数数量。
          */
         for(int atNum = 2; listOfPrimes.size() < numOfPrimesToList; atNum++) {
            
             /* 当要除以的数字的索引小于我们列表的长度时,我们执行以下操作:
              */
             for(int intIndexToCheck = 0; intIndexToCheck < listOfPrimes.size(); intIndexToCheck++) {
                
                 /* 如果我们正在测试的数字除以要除以的那个数的余数
                  * 大于零,则增加其可能是质数的计数器。
                  */
                 if(atNum % listOfPrimes.get(intIndexToCheck) < 0) {
                     possiblePrimeCounter++;
                    
                     /* 如果它可能是质数的机会为 1(也就是说,
                      * 给它机会的次数等于可能的机会总数),那么
                      * 我们可以认为它是一个质数。
                      */
                     if(possiblePrimeCounter == listOfPrimes.size()) {
                         //然后我们将此数字添加到质数列表中。
                         listOfPrimes.add(atNum);
                        
                         possiblePrimeCounter = 0;
                     }
                 }
             }
         }
         //最后,我们打印出质数列表。
         System.out.println(listOfPrimes);
     }
}

返回结果:

[2, -2147483647, -2147483645, -2147483644, -2147483643, -2147483641, -2147483640, -2147483639, -2147483638, -2147483637]
英文:

I have a program that lists prime numbers. I started with a positive integer and it returned an array(it's supposed to do this) that contained negative numbers(not supposed to do this). The problem is there's no decrement operator anywhere in the code, only increment operators and modulus functions. Here is the whole code and output for your reference, completely commented for easy understanding:

package calculations;

import java.util.ArrayList;

public class PrimeNumbers {
 public static void main(String[] args) {
 	
 	 //Declaring variables to be used...
 	 ArrayList&lt;Integer&gt; listOfPrimes = new ArrayList&lt;Integer&gt;();
 	 listOfPrimes.add(2);
	 int numOfPrimesToList = 10;
	 int possiblePrimeCounter  = 0;
	 
	 /* We start testing at the number 2 and increment until 
	  * the list of primes we have listed is equal to the
	  * number of primes want to list. 
	  */
	 for(int atNum = 2; listOfPrimes.size() &lt; numOfPrimesToList; atNum++) {
		
		 /* While the index of the number to divide from 
		  * is less than the length of our list, we do 
		  * the following:
		  */
		 for(int intIndexToCheck = 0; intIndexToCheck &lt; listOfPrimes.size(); intIndexToCheck++) {
			
			 /* If the modulus of the number we are testing 
			  * and the one are dividing by is greater than
			  * zero, we increment its possibility of being
			  * a prime by one. 
			  */
			 if(atNum % listOfPrimes.get(intIndexToCheck) &lt; 0) {
				 possiblePrimeCounter++;
				
				 /* If its chance of being a prime is 1 (that is, the
				  * times it has been given a chance is equal to the
				  * total number of possible chances it is given), then
				  * we can consider it to be a prime.
				  */
				 if(possiblePrimeCounter == listOfPrimes.size()) {
					 //We then add this number to the list of primes.
					 listOfPrimes.add(atNum);
					
					 possiblePrimeCounter = 0;
				 }
			 }
		 }
	 }
	 //Finally, we print out the list of primes.
	 System.out.println(listOfPrimes);
 }
}

Returns:

[2, -2147483647, -2147483645, -2147483644, -2147483643, -2147483641, -2147483640, -2147483639, -2147483638, -2147483637]

答案1

得分: 1

发生的情况被称为整数溢出
当整数达到最大值(Integer.MAX_VALUE)时,如果尝试进行递增,它将回到最小值(Integer.MIN_VALUE),这就是你得到的数字。

英文:

What is happening is called Integer Overflow.
When int becomes the maximum value (Integer.MAX_VALUE), if you try to increment, it will go back to its smallest value (Integer.MIN_VALUE) which is the number you are getting.

答案2

得分: 0

问题在于,你的代码并没有执行你的注释所述的操作。你有以下代码:

         /* 如果我们正在测试的数字与我们正在除以的数字的模数大于零,
          * 我们会将其成为可能是素数的可能性加一。
          */
         if(atNum % listOfPrimes.get(intIndexToCheck) &lt; 0) {

虽然注释中说你检查的是大于零,但实际上它检查的是小于零。将这行代码更改为实际执行注释所描述的操作:

         if(atNum % listOfPrimes.get(intIndexToCheck) &gt; 0) {

因为你在测试小于零的余数,这在正数情况下永远不会发生,所以你会不断增加你的数字,直到溢出并变为负数,此时余数确实变为小于零。

针对你后续的问题,如果你的数字不是素数,possiblePrimeCounter 没有被重置,所以 possiblePrimeCounter 会继续测试下一个数字。另外,在添加了一个素数后,你又进行了另一次测试,并检查它是否能够被自身整除(因为你刚刚增加了列表的大小)。

一个简单的修复方法是:

     possiblePrimeCounter = 0; // 在尝试每个新数字之前需要重置
     for(int intIndexToCheck = 0; intIndexToCheck &lt; listOfPrimes.size(); intIndexToCheck++) {

或者使循环更加高效,一旦我们知道数字不是素数,就没有必要继续测试。

     possiblePrimeCounter = 0;

     for(int intIndexToCheck = 0; intIndexToCheck &lt; listOfPrimes.size(); intIndexToCheck++) {
         if(atNum % listOfPrimes.get(intIndexToCheck) !=0) {
             possiblePrimeCounter++;
             if(possiblePrimeCounter == listOfPrimes.size()) {
                 // 然后将此数字添加到素数列表中。
                 listOfPrimes.add(atNum);
                
                 possiblePrimeCounter = 0;
             }
         } else {
             break; // 不是素数
         }
     }
英文:

The problem is That your code does not do what your comment says it does. You have

         /* If the modulus of the number we are testing 
          * and the one are dividing by is greater than
          * zero, we increment its possibility of being
          * a prime by one. 
          */
         if(atNum % listOfPrimes.get(intIndexToCheck) &lt; 0) {

Where it says that you check for greater than zero, but in reality it checks for less than zero. Change the line to actually do what the comment says

         if(atNum % listOfPrimes.get(intIndexToCheck) &gt; 0) {

Since you are testing for remainder of less than zero which never happens for positive numbers you keep increasing your number until it overflows and becomes negative at which time the remainder does become less than zero.

For your follow up question, if your number isn't a prime, the possiblePrimeCounter isn't reset, so the possiblePrimeCounter carries on for testing the next number. Also, after adding a prime number you do yet another test and check if it is divisible by it selves (since you just increased the size of the list).

A simple fix would be

     possiblePrimeCounter = 0; // Need to reset before trying each new number
     for(int intIndexToCheck = 0; intIndexToCheck &lt; listOfPrimes.size(); intIndexToCheck++) {

or make the loop somewhat efficient, as soon as we know the number isn't a prime there is no need to continue testing.

     possiblePrimeCounter = 0;

     for(int intIndexToCheck = 0; intIndexToCheck &lt; listOfPrimes.size(); intIndexToCheck++) {
         if(atNum % listOfPrimes.get(intIndexToCheck) !=0) {
             possiblePrimeCounter++;
             if(possiblePrimeCounter == listOfPrimes.size()) {
                 //We then add this number to the list of primes.
                 listOfPrimes.add(atNum);
                
                 possiblePrimeCounter = 0;
             }
         } else {
             break; // Not prime
         }
     }

huangapple
  • 本文由 发表于 2020年8月23日 21:12:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/63547355.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定