计算GCD时出现浮点异常(核心已转储)

3

我正在编写一个程序,将分数化简到最简形式。以下是我的程序:

#include <stdio.h>
int main(){
    int m,x,n,gcd;
    printf("Enter a fraction: ");
    scanf("%d/%d",&n,&m);

    if(m==0)printf("Error");
    else
        for(;;){
           x=m%n;
           if(x==0){
              gcd=n;
              m/=gcd;
              n/=gcd;
              printf("In lowest terms: %d/%d",n,m);
            }else
                m=n;
                n=x;
         }

    return 0;
}

我使用欧几里得算法来计算最大公约数。当执行时,它报告:

浮点异常(核心已转储)

我的代码有什么问题?

3
浮点异常通常在整数被零除时发生。因此,请注意 /% 运算符,并检查 n == 0 的情况。您可能还需要检查 scanf 的返回值,它应该是2。 - M Oehm
4
鉴于上面的评论,我不禁注意到n=x这一行的缩进。看起来你想把它作为else的一部分,但实际上并不是(你没有用{}将多个表达式括起来)。当x=0时,n也会被设为零。 - paddy
2个回答

5
您在这里遇到了块级作用域问题:
if(x==0){
    // ...
}else
    m=n;
    n=x;

这将被执行为:

这将被执行为:

if(x==0){
    // ...
}else{
    m=n;
}
n=x;

这意味着当x为零时,在循环结束时n被设置为零。 当再次计算m%n时,会出现问题。 或者如果由于某种原因它能给出值而不崩溃您的程序,那么gcd = n将在随后将mn除以gcd时导致除以零
如果您想要多个语句成为else分支的一部分,则需要将它们用大括号括起来,如下所示:
if(x==0){
    // ...
}else{
    m=n;
    n=x;
}

事实上,即使只有一个语句,始终使用大括号也是一个好习惯。 在我的工作场所,这甚至包含在我们的编码标准和代码审查过程中。


是的,@paddy。我忘记使用大括号了,所以结果很混乱。但实际上我的代码是有问题的。我需要再检查一遍。 - villianNoob

0

@paddy 是的,我没有看清楚。无论如何,我的代码从一开始就有缺陷。我使用for(;;)创建循环,但我告诉它在else处停止。这是完全错误的,因为循环将再次执行并创建一个无限循环。此外,我打算将gcd分配给n,但在此之前,n被分配给了x(在此情况下,在else之后,循环被执行)。因此,如果x0,那么m/=gcdn/=gcd可能会导致core dumped。这是一个愚蠢的代码,我不应该提出这个问题。所以我重新思考并重写了代码。

#include <stdio.h>
    int main(){
    int m,x,n,gcd;
    int M,N;

    printf("Enter a fraction: ");
    scanf("%d/%d",&n,&m);
    M = m;
    N = n;

     if(m==0)printf("Error");
        else
        do{
           x=m%n;
           m=n;
           n=x;
             }while(x!=0);
    gcd=m;
    M/=gcd;
    N/=gcd;

    printf("In lowest terms: %d/%d\n",N,M);

    return 0;
}

因为在循环后,mn已经被修改了,所以m/=gcdn/=gcd不能返回准确的结果。因此,我将n赋值给N,将m赋值给M,这样我输入的值就不会改变。将gcd赋值给m有点棘手,但并不是错误的,因为在此之前m被赋值给了n。所以我认为这个技巧会产生相同的效果。我使用do while循环,因为我可以设置“终止点”,这样就不会出现无限循环


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接