4
#include <stdio.h>
#include <math.h>

// #define LIMIT 600851475143
int isP(long i);
void run();
// 6857
int main()
{
    //int i = 6857;
    //printf("%d\n", isP(i));
     run();
}

void run()
{
long LIMIT = 600851475143;
// 3, 5
// under 1000

long i, largest =1, temp=0;
for(i=3; i<=775147; i+=2)
{
    temp = ((LIMIT/i)*i);
if(LIMIT == temp)
    if(isP(i)==1)
            largest = i;
}
printf("%d\n",largest);
}

int isP(long i)
{
long j;
for(j=3; j<= i/2; j+=2)
    if(i == (i/j)*j)
        return 0;

return 1;

}

我刚刚遇到了一个有趣的问题。如上所示,这段代码旨在计算 LIMIT 的最大素数。上面显示的程序给我的答案是 29,这是不正确的。

虽然奇迹般地,当我定义 LIMIT 值(而不是将其声明为 long)时,它可以给我正确的值:6857。

有人可以帮我找出原因吗?非常感谢!

4

6 回答 6

3

许多平台上的Along是一个 4 字节整数,并且会在2,147,483,647. 例如,请参阅Visual C++ 的数据类型范围页面。

当您使用 a#define时,编译器可以自由选择一个更合适的类型,它可以容纳您的非常大的数字。这可以使其行为正确,并为您提供您期望的答案。

但是,总的来说,我建议明确说明数据类型,并尽可能选择能够正确表示数字而不需要编译器和平台特定行为的数据类型。

于 2013-03-06T17:11:28.207 回答
1

我会怀疑这里有数字类型问题。

#define是一个预处理器指令,因此它会LIMIT在运行编译器之前替换为代码中的那个数字。这为编译器打开了大门,可以按照它想要的方式解释该数字,这可能不是long.

在您的情况下,long可能还不够大,因此编译器在您使用#define. 为了获得一致的行为,您应该指定一个您知道具有适当范围的类型,而不是依赖编译器来正确猜测。

您还应该在编译器上打开完整警告,它可能能够为您检测到此类问题。

于 2013-03-06T17:09:49.523 回答
1

当您输入如下表达式时:

(600851475143 + 1)

一切都很好,因为编译器会自动将这两个常量提升为long long足够大以执行计算的适当类型(如您的情况)。你可以用这种方式做尽可能多的表达式。但是当你写:

long n = 600851475143;

编译器尝试将 a long long(或任何常量隐式转换为)分配给 a long,这会在您的情况下导致问题。你的编译器应该警告你,例如 gcc 说:

warning: overflow in implicit constant conversion [-Woverflow]

当然,如果 along大到足以容纳该值,则没有问题,因为常量将是大小相同long或更小的类型。

于 2013-03-06T17:24:39.373 回答
0

可能是因为600851475143大于LONG_MAX(根据this 2147483647 )

于 2013-03-06T17:10:42.160 回答
0

尝试用“long long”替换限制类型。它的立场,它环绕(尝试打印限制为长)。预处理器知道这一点并使用正确的类型。

于 2013-03-06T17:14:37.760 回答
0

您的代码基本上减少了这两种可能性:

long LIMIT = 600851475143;
x = LIMIT / i;

对比

#define LIMIT 600851475143
x = LIMIT / i;

第一个等效于将常量转换为long

x = (long)600851475143 / i;

而第二个将被预编译成:

x = 600851475143 / i;

区别就在这里:600851475143对于你的编译器类型来说太大了,long所以如果它被转换成long它就会溢出并发疯。但如果直接在除法中使用,编译器知道它不适合 a long,自动将其解释为long long文字,i提升 the 并将除法作为 a 完成long long

但是请注意,即使该算法在大多数情况下似乎都有效,但您仍然在其他地方发生溢出,因此代码不正确。您应该将任何可能包含这些大值的变量声明为long long.

于 2013-03-06T17:26:52.457 回答