Почему я получаю исключение 8 с плавающей запятой? - PullRequest
0 голосов
/ 01 ноября 2018

Для моего вступления. к обзору программных экзаменов меня попросили написать программу, которая использует функцию для вычисления gcd набора чисел. Я написал следующий код, который иногда, кажется, работает нормально, но другие возвращают Исключение с плавающей точкой 8. Я надеялся, что кто-то может пролить свет.

Я выполнил это, используя clang gcd.c -o gcd на Mac-терминале, используя macOS High Sierra и числа, которые возвращают ошибку 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;
}

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

первое впечатление в цикле 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 на самом деле не добавляют никакого значения, потому что есть return в if

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;
}
0 голосов
/ 01 ноября 2018

Выглядит как пара ошибок в вашем коде для поиска GCD.

Вам следует обновить значение a[i+1] в цикле for вместо a[i]. И GCD будет a[n-1] -ым элементом после этого изменения. Когда вы выполняете итерации по циклу, 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]); 
}

В цикле while из gcd() необходимо внести следующие изменения. Проверьте наличие условия a==b и измените два условия if на условия if-else. Если b является фактором a, a становится 0 в вашем первом if состоянии. Затем во втором состоянии вы делаете % 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);
    }
}
...