【问题标题】:Find the largest prime factor of a given number找到给定数字的最大素数
【发布时间】:2021-05-12 16:44:58
【问题描述】:

我正在编写这个方法,它应该返回给定数字的最大素数。它工作正常,直到输入 45 并且输出为 15,即使输出应该是 5。我正在努力寻找错误。请帮忙。

public static int getLargestPrime(int number) {

        if (number < 0) {
            return -1;
        }

        for (int i = number-1; i > 1; i--) {
            if (number % i == 0) {
                for (int j = 2; j < i; j++) {
                    if (i % j == 0) {
                        continue;
                    }
                    return i;
                }
            }
        }
        return -1;

    }

【问题讨论】:

  • 看来您需要break; 而不是continue;

标签: java loops primes


【解决方案1】:

您需要添加一个标志来检查值i 的可分性。只有当i 是质数时,它才会保持正确。稍后如果标志仍然为真,您可以返回i 否则您需要继续迭代

您的代码中发生的情况是,当 i=15 时,内部循环从 2 开始迭代,15%2!=0 因此它跳过了 if 条件并返回 15

for (int i = number-1; i > 1; i--) {
        if (number % i == 0) {
            bool flag = true;
            for (int j = 2; j < i; j++) {
                if (i % j == 0) {
                    flag = false;
                    break;
                }
            }
            if(flag)
                return i;
        }
    }

【讨论】:

    【解决方案2】:

    简而言之:“主要”验证是错误的。

    在您的代码中,在内部循环中,您希望所有数字都是“i”的因数,这当然是错误的。

    您的代码将检索输入的最大因子,其中有一个数字不是它的因子(i % j != 0),因此是它的最大因子(无论素数如何)。

    【讨论】:

      【解决方案3】:
      1. 查找输入数之前的素数
      2. 以相反的顺序对质数进行排序
      3. 遍历素数并检查它是否是一个精确的倍数
      4. 如果它是一个精确的倍数,则返回素数
      import java.util.ArrayList;
      import java.util.Collections;
      import java.util.List;
      import java.util.Optional;
      
      class PrimeFactorTest {
      
          public static void main(String[] args) throws Exception {
              int[] inputs = new int[]{-100, -25, -2, -1, 0, 1, 2, 3, 4, 5, 100, 1223, 2000, 874032849,
                  Integer.MAX_VALUE, Integer.MAX_VALUE};
      
              for (final int input : inputs) {
                  Optional primeFactor = largestPrimeFactor(input);
                  if (primeFactor.isPresent()) {
                      System.out.println("Largest Prime Factor of " + input + " is " + primeFactor.get());
                  } else {
                      System.out.println("No Prime Factor for " + input);
                  }
              }
          }
      
          public static Optional<Integer> largestPrimeFactor(final int input) {
              if (input < 0) {
                  return largestPrimeFactor(Math.abs(input));
              }
              final int sqrt = (int) Math.sqrt(input);
              List<Integer> primes = getPrimesInDescendingOrder(sqrt);
              if (primes.size() == 0) {
                  return Optional.empty();
              }
              for (final int prime : primes) {
                  if (input % prime == 0) {
                      return Optional.of(prime);
                  }
              }
              return Optional.of(input);
          }
      
          private static List<Integer> getPrimesInDescendingOrder(final int input) {
              if (input < 2) {
                  return new ArrayList<>();
              }
              List<Integer> primes = new ArrayList<>();
              primes.add(2);
              for (int current = 3; current <= input; current++) {
                  boolean isPrime = true;
                  for (int prime : primes) {
                      if (current % prime == 0) {
                          isPrime = false;
                      }
                  }
                  if (isPrime) {
                      primes.add(current);
                  }
              }
              primes.sort(Collections.reverseOrder());
              return Collections.unmodifiableList(primes);
          }
      }
      

      【讨论】:

        【解决方案4】:

        我想出了这个。如果您从 2 开始并逐步向上,那么您将在命中它们之前消除所有非质数,因为它们将不再是余数的因数。

        import static org.junit.Assert.assertEquals;
        
        import org.junit.Test;
        
        public class LargestPrimeFactor {
            @Test
            public void testGetLargestPrime() {
                assertEquals(2, getLargestPrime(2));
                assertEquals(3, getLargestPrime(3));
                assertEquals(2, getLargestPrime(4));
                assertEquals(5, getLargestPrime(5));
                assertEquals(3, getLargestPrime(6));
                assertEquals(7, getLargestPrime(7));
                assertEquals(2, getLargestPrime(8));
                assertEquals(3, getLargestPrime(9));
                
                assertEquals(23, getLargestPrime(23*23*7*2*5*11*11));
            }
        
            int getLargestPrime(int number) {
                for (int i = 2; number > i; i++) {
                    while (number > i && number % i == 0) {
                        number = number / i;
                    }
                }
                return number;
            }
        }
        

        【讨论】:

          【解决方案5】:

          在达到 45 之前它不能正常工作。它在 4、8、12、16、18、20、24、27、28、30、32、36、40、42 和 44 失败。它返回-1 表示每个素数,这是正确的,但它也返回 -1 表示 4。它通常会找到最大的因子,不管它是否是素数。

          您的外部循环查找因子,从最大的开始。你的内循环没有意义。它需要对素数进行测试。看起来你的意思是它在找到 i 的一个因子时退出,但它并没有这样做。相反,当它发现一个不是一个因素的数字时,它就会退出。 continue 语句告诉它转到 j 的下一个值。您可能打算让它继续到 i 的下一个值。为此,您可以使用 break。那将摆脱内部循环。或者您可以标记外部循环并在 continue 语句中使用该标签,这可能是您的想法:

          candidates:
          for (int i = number - 1; i > 1; i--) {
            if (number % i == 0) {
              for (int j = 2; j < i; j++) {
                if (i % j == 0) {
                  continue candidates; // This continues the outer loop
                }
                return i;
              }
            }
          }
          return -1;
          

          这让你更接近,但它仍然失败为 2 的幂,以及它找到 p^n 其中 p 是素数的情况。

          此外,以数字 1 开始外循环是没有意义的。您可以跳过所有高于 number/2 的数字。它们都不会产生模零。

          【讨论】:

            【解决方案6】:

            我建议做这样的事情。首先,考虑2*2*3*47 = 564564 is &lt;= 24 的平方根。所以你需要做的就是除以24的数字。首先,消除2。剩下3*47。接下来是3,留下47。由于4 thru 24 中没有其他数字可以除以47,因此47 必须是质数。如果它是复合的,它的主要因数会被较早的除数之一分解出来。

            这可以通过在单独的循环中分解出2 来进一步优化。然后从3 开始,只除以奇数(2 已经消除了偶数因子,如果有的话)。

            如果在数字减为 1 时出现这种情况,那么最后进行减法的除数必须是最大的素数。

            int[] testData = { 2, 10, 2 * 2 * 5, 2 * 3 * 47 * 5,
                    2 * 2 * 2 * 3 * 3 * 3 * 17 * 17 * 17 };
            for (int v : testData) {
                System.out.printf("%8s - largest prime factor = %s%n", v,
                        getLargestPrime(v));
            }
            

            打印

                   2 - largest prime factor = 2
                  10 - largest prime factor = 5
                  20 - largest prime factor = 5
                1410 - largest prime factor = 47
             1061208 - largest prime factor = 17
            

            方法

            public static int getLargestPrime(int number) {
                // no primes less than 2 exist.
                if (number < 2) {
                    return -1;
                }
                while (number % 2 == 0) {
                    number /= 2;
                }
                
                int lastDivisor = 2;
                for (int d = 3; d <= Math.sqrt(number); d += 2) {
                    lastDivisor = d;
                    while (number % d == 0) {
                        number /= d;
                    }
                }
                
                return number == 1 ? lastDivisor : number;
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2015-11-18
              • 2013-09-09
              • 1970-01-01
              • 2016-09-08
              • 1970-01-01
              • 2017-03-05
              • 1970-01-01
              相关资源
              最近更新 更多