C中的浮点异常

时间:2014-08-18 08:47:28

标签: c exception floating-point

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

long fctl(int n){
  int a=1,i;
  for(i=n;i>1;--i)
    a*=i;
  return a;
}

long ch(int n, int r){
  return fctl(n) / (fctl(n-r)*fctl(r));
}

int main(){
  char *hands[] = {"onepair", "twopair", "triple", "straight", "flush", "fullhouse", "fourofakind", "straightflush", "royalflush"};
  double handprobs[9];

  handprobs[0] = ch(13,1)*ch(4,2) * ch(12,3)*pow(ch(4,1), 3) / ch(52,5);
  handprobs[1] = ch(13,2)*pow(ch(4,2), 2) * ch(11,1)*ch(4,1) / ch(52,5);
  handprobs[2] = ch(13,1)*ch(4,3) * ch(12,2)*pow(ch(4,1), 2) / ch(52,5);
  handprobs[3] = 10.0 * pow(ch(4, 1),5) / ch(52, 5)  -  10.0/ch(52,5) - 4.0/ch(52,5);
  handprobs[4] = ch(13,5)*ch(4,1) / ch(52, 5) - 10.0/ch(52,5);
  handprobs[5] = ch(13,1)*ch(4,3) * ch(12,1)*ch(4,2) / ch(52,5);
  handprobs[6] = ch(13,1)*1 * ch(12,1)*ch(4,1) / ch(52,5);
  handprobs[7] = 40.0 / ch(52, 5) - 4.0/ch(52,5),
  handprobs[8] = 4.0 / ch(52, 5);
  int i;
  for(i=0;hands[i];++i){
    printf("%s\t%f\n",hands[i], handprobs[i]);
  }
}

当我编译它时返回&#34;浮点异常(核心转储)&#34;,不知道为什么。 (尝试用(双)转换所有的probs。)任何想法?

2 个答案:

答案 0 :(得分:1)

fctl(52)int来说太大了。您将不得不重新考虑进行此计算的方法。您可以输出INT_MAX以查看实际可以走多远。您可以使用unsigned long long(参见ULLONG_MAX)购买更多空间,但对于52!来说,这仍然不够大。

调用整数溢出会导致未定义的行为; &#34;浮点异常&#34;通常意味着尝试将整数除以零,这在您尝试的计算加上它们溢出的事实时是合理的。不要问我为什么这被报告为FPE,尽管事实上它并没有涉及任何浮动点。 (可能&#34;历史原因&#34;)

答案 1 :(得分:1)

接受回答后。

@Matt McNabb井指出,fctl(52)对于适合long的虚拟数值结果而言非常重要。 (@mrVoid断言需要225位int。)

但某些@LưuVĩnhPhúc正在走上正确轨道,以了解导致例外的原因。

fctl(x)将是数字1x的乘积,其中一半是偶数。因此fctl(x)x/2个LSbits设置为零。

假设32位int,一旦fctl(n-r)fctl(r)的LSBits数超过/满足32,产品(fctl(n-r)*fctl(r))将为0且return fctl(n) / (0);抛出异常。

在许多系统上,整数除以0被报告为浮点错误。我认为这种奇怪的现象是为了简化陷阱处理。