【问题标题】:Why do I get floating point exception 8?为什么会出现浮点异常 8?
【发布时间】:2018-11-01 04:23:15
【问题描述】:

对于我的介绍。为了编程考试复习,我被要求编写一个程序,该程序使用一个函数来计算一组数字的 gcd。我编写了以下代码,有时似乎可以正常工作,但其他代码返回浮点异常 8。我希望有人能阐明一下。

我在使用 macOS High Sierra 的 mac 终端上使用 clang gcd.c -o gcd 进行了编译,返回 FP 错误的数字是 5372 18960 -230048 1185 16486

这是代码:

#include <stdio.h>
#include <stdlib.h>

int gcd(int a, int b){
    if((a==0) || (b==0)){
        return 0;
    }else{
        if( a % b == 0 ){
            return b;
        }else{
            if ( b % a == 0 ){
                return a;
            }
        }
    }
    while( (a != 0) && (b != 0) ){
        if (abs(a)>abs(b)){
            a = abs(a) % abs(b);
        }
        if(b>a){
            b = abs(b) % abs(a);
        }
    }
    if (a == 0){
        return b;
    }else{
        return a;
        }
}

int main(void){
    int n;
    printf("Please enter the number of integers in your array:\n");
    scanf("%d", &n);

    int a[n];

    printf("Please enter the numbers in your arrray:\n");

    for (int i = 0; i < n; ++i){
        scanf("%d", &a[i]);
    }

    for (int i = 0; i < (n-1); ++i){
            a[i] = gcd(a[i], a[i+1]); 
    }

    printf("The gcd of the %d numbers is %d .\n", n, a[n-2]);

    return 0;
}

【问题讨论】:

  • for (int i = 1; i &lt;= n; 我们又来了。假设 n==2。有多少个数字?第一个数字的索引是多少?最后一个数字的索引是多少? &lt;=2的自然数是多少?
  • @n.m 不错的收获。但即便如此,没有 FP 操作的程序抛出 FP 错误是相当疯狂的。会不会是一个解释器,它使用双精度来做 int 算术或类似的奇怪的东西? AlexD,您确实需要在此类问题中包含有关您环境的信息。
  • @Gene 除以零通常会导致 FP 错误,即使它是整数。
  • 查看此代码for (int i = 0; i &lt; (n-1); ++i){ a[i] = gcd(a[i], a[i-1]); } 第一次迭代时a[i-1] 是什么?
  • 注意:abs(INT_MIN) 是 UB。不清楚gcd()abs()需要

标签: c greatest-common-divisor


【解决方案1】:

看起来你的代码中有几个错误用于查找 GCD。

您应该在 for 循环中更新 a[i+1] 的值,而不是更新 a[i]。在此更改之后,GCD 将是 a[n-1]th 元素。当您遍历循环时,a[i]a[i+1] 在您的情况下将是原始(输入)值。因此,如果其他一切正常,您的结果将是数组最后两个元素的 GCD(a[n-2]a[n-1])。

for (int i = 0; i < (n-1); ++i) {
    a[i+1] = gcd(a[i], a[i+1]); 
}

gcd()while循环中,需要做如下修改。检查a==b 条件并将两个if 条件更改为if-else 条件。如果ba 的一个因子,则a 在您的第一个if 条件中变为0。然后在第二种情况下,您正在执行% 0,这会引发错误。

while( (a != 0) && (b != 0) ){
    if (abs(a)>=abs(b){
        a = abs(a) % abs(b);
    }
    else if(abs(b)>abs(a)){
        b = abs(b) % abs(a);
    }
}

【讨论】:

  • 虽然@u__ 之前说过,但我是个白痴,直到你说出来才意识到我错过了 else 语句。 +1 对两者都非常感谢。
  • else if(abs(b)&gt;abs(a)){ 当然可以简化为else {
【解决方案2】:

下面while循环中的第一印象

while( (a != 0) && (b != 0) ){
    if (abs(a)>abs(b)){
        a = abs(a) % abs(b); // value of a is altered and reused 
    }
    if(b>a){
        b = abs(b) % abs(a);  // here <-- and could very well be a 0
    }
}

在完全不同的情况下,您可以删除 else {} 块,如果您可以花一点时间看看 else 块并没有真正增加任何价值,因为在 if 中有一个 return

int gcd(int a, int b){

    /** sanity checks */
    if((a==0) || (b==0))
        return 0;

    /* few more obvious checks */
     if( a % b == 0 )
        return b;
     if( b % a == 0 )
        return a;

    /* Real Logic */
     while( (a != 0) && (b != 0) ){
        if (abs(a)>abs(b)){
            a = abs(a) % abs(b);
        }
        else if(abs(b) > abs(a) ){
            b = abs(b) % abs(a);
        }
    }

    /* Final results */
    return (a == 0) ? b : a;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多