GCD代码中的浮点异常

时间:2018-01-10 08:17:39

标签: c++ floating-point-exceptions

我正在创建一个程序来使用Euclidian方法计算两个数字的gcd,但是我得到了一个浮点异常错误。我该怎么办?

/*
 Euclidian Greatest Common Divisor Key Lemma 
 if gcd(a,b) = gcd(a',b) = gcd(b,a') Where a' = a % b
 Proof
 let a = a' + bq ... (1) , where q is some number
 if d is the gcd then b is divisible by d and also a is divisible by d
 then from the equation(1) we can see that a' is also divisible by d.
*/

#include<iostream>

using namespace std;

int euclidgcd(int a, int b)
{
    int c = a % b;
    if(b == 0)
    {
        return a;
    }
    else
    {
        return euclidgcd(b, c);
    }
}

int main()
{
   int a,b;
   std::cout << "give a and b where a > b" << '\n';
   std::cin >> a >> b;
   int d = euclidgcd(a, b);
   return 0;
}

1 个答案:

答案 0 :(得分:0)

这是因为代码除以零,产生SIGFPE。 在使用调试符号和ASAN支持(需要g ++或clang)编译代码时,可以很容易地看到这一点:

$ g++ -g -fsanitize=address -fsanitize=undefined -std=c++11  gcd.cpp; ./a.out 
give a and b where a > b
20
10
gcd.cpp:16:15: runtime error: division by zero
ASAN:DEADLYSIGNAL
=================================================================
==19101==ERROR: AddressSanitizer: FPE on unknown address 0x555b8634a4d8 (pc 0x555b8634a4d8 bp 0x7fffa1b82b00 sp 0x7fffa1b82ad0 T0)
    #0 0x555b8634a4d7 in euclidgcd(int, int) ./gcd.cpp:16
    #1 0x555b8634a4f6 in euclidgcd(int, int) ./gcd.cpp:23
    #2 0x555b8634a7fb in main ./gcd.cpp:32
    #3 0x7f8e99f071c0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x211c0)
    #4 0x555b8634a3a9 in _start (./a.out+0x13a9)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: FPE ./gcd.cpp:16 in euclidgcd(int, int)
==19101==ABORTING

问题源代码行(16)就是这个:

int c = a % b;

要获得更多见解,请在调试器(例如gdb)中运行该程序:

$ gdb ./a.out 

(gdb) run
Starting program: /home/steemann/a.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
give a and b where a > b
20
10
gcd.cpp:16:15: runtime error: division by zero

Program received signal SIGFPE, Arithmetic exception.
0x00005555555554d8 in euclidgcd (a=10, b=0) at gcd.cpp:16
16      int c = a % b;

此程序失败,因为b的值为0,因此执行除零。

您可以通过在划分或计算模数之前测试b为非零来避免这种情况。一般来说,这是一种很好的做法,可以避免程序崩溃。