public static void main(String[] args) {
int sum = 2;
int isPrime;
for(int x = 3; x < 2000000; x+=2){//x is the number we check for if it is a prime
isPrime = 0;
int y = 3;
while(isPrime == 0) {
if(x%y==0){
isPrime = 1;
}
if(y > Math.ceil(x/2)) {
isPrime = 1;
sum+=x;
}
y += 2;
}
}
System.out.println(sum);
}
所以我试图找到低于2 000 000的素数之和,我已经检查过,这个代码适用于x&lt;我无法弄清楚当接近2 000 000时会发生什么情况,但有些事情确实存在。如果你能找到原因,我将不胜感激。
答案 0 :(得分:3)
这是因为名为integer overflow的东西。简而言之,它指的是计算机中的整数具有最大位数(即二进制数字)的概念。 int
最多包含32位,这意味着无符号系统中可能的最大数量为2^32-1
。如果你在这个数字上加1,你得到0
,因为没有更多数字可以携带1!
因此,对于您的代码,使用long
(具有64位限制):
long sum = 2;
for(int i = 3 ; i < 2000000 ; i+=2) if(/*i is Prime*/) sum += i;
System.out.println(sum);
这是一个解释它是什么的YouTube video。
答案 1 :(得分:2)
int
是签名号码,其中最大可能值为2 31 - 1.由于您的最大值约为200万,您只能需要超过1000个这个大小的值才能超过约20亿的限制。超过此限制时,int
类型保留最低32位,而不是抛出错误,这看起来像一个理智的结果,但实际上是错误的。
BTW您可以通过替换
来查看何时发生这种情况sum+=x;
与
sum = Math.addExact(sum, x);
检查溢出。
public static int addExact(int x, int y) {
int r = x + y;
// HD 2-12 Overflow iff both arguments have the opposite sign of the result
if (((x ^ r) & (y ^ r)) < 0) {
throw new ArithmeticException("integer overflow");
}
return r;
}
我建议使用long
,其限额约为9亿亿美元。
BTW如果您需要所有素数达到已知限制,使用Sieve of Eratosthenes可能是一种更有效的解决方案。如果要随机检查数字,搜索数字的所有可能因素往往会更有效。
以下是我将如何编写使用long
并简化代码的方法。
public static void main(String... args) {
long sum = 2;
for(int x = 3; x < 2000000; x += 2)
if (isPrime(x))
sum += x;
System.out.println(sum);
}
/**
* @param x is the number we check for if it is a prime
*/
static boolean isPrime(long x) {
if (x % 2 == 0)
return false;
for (int y = 3; y * y <= x; y += 2)
if (x % y == 0)
return false;
return true;
}
答案 2 :(得分:1)
你的程序有2个问题,第一个由@Malijam指定,答案会溢出。
第二个是关于复杂性O(n^2)
最坏的情况。这太多了。
您可以通过检查小于候选数字平方根的因子来稍微修改您的代码O(n * sqrt(n))
。
修改后的代码:
public static void main(String[] args) {
long sum = 2;
long isPrime;
for(int x = 3; x < 2000000; x+=2){//x is the number we check for if it is a prime
isPrime = 0;
long y = 3;
while(isPrime == 0) {
if(x%y==0){
isPrime = 1;
}
if(y*y > x) {
isPrime = 1;
sum+=x;
}
y += 2;
}
}
System.out.println(sum);
}
Ideone上的演示:http://ideone.com/k1XAuA
答案 3 :(得分:0)
您的代码似乎可以在我的计算机上运行。代码打印1179908154,与uSeemSurprised的答案中显示的不同,但它应该让你输出。算术程序花了很长时间(大约2分钟),但它工作正常。根据计算机的功率,可能需要很长时间。
PS:我做了一些修改,使程序没有花费那么长时间。我转身
if(y> Math.ceil(x / 2))
到
如果(Y * 3 X的催化剂)
当您运行数百万次代码时,调用Math.ceil非常低效。我认为乘法也比分裂快。我还在for循环之外移动了int的声明。结果代码的速度是原来的三倍。答案 4 :(得分:0)
一般答案: 您可以在下面的代码中找到所有素数中的一些:
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
long long int tc,N;
unsigned long long int sum=0;
vector <long long int>v;
long long int arr[1000000] = {0},i,j;
for (i = 2; i < 1000000; i++)
{
for ( j = i * i; j < 1000000; j+=i)
{
arr[j - 1] = 1;
}
}
for (int i = 1; i < 1000000; i++)
{
if (arr[i - 1] == 0)
v.push_back(i);
}
cout<<"\nEnter the number:";
cin>>N;
i=1;
while(v.at(i)<=N)
{
sum+=v.at(i);
i++;
}
cout<<sum<<"\n";
sum=0;
return 0;
}