首页 > 解决方案 > 为什么在调用 realloc() 后,模运算会出现浮点异常?

问题描述

我写了这段代码来找到第x个最大的素数:

for (int i = 3 /* 2 has already been added to the list */; i < maxNumber; i += 2) {
  for (int tested = 0; ; tested++) {
    if (primes[tested] == 0) {
      break;
    }
    if (i % (int) primes[tested] == 0) {
      goto loop;
    }
  }

  count++;
  if (count == primesSize) {
    primesSize += 2000;
    primes = (double*) realloc(primes, sizeof(double) * primesSize);
  }

  primes[count - 1] = i;
  printf("Prime number #%d: %d\n", count, i);
  printf("Prime size: %d\n", primesSize);

  loop: /* statement that does nothing */ if (1) {}
}

但是,当使用大数字(> 8,000)时,它返回了“浮点异常”。

什么时候发生在这里:


当我过去gdb查找错误原因时,我发现这部分是问题的原因:

for (int tested = 0; ; tested++) {
  if (primes[tested] == 0) {
    break;
  }
  if (i % (int) primes[tested] == 0 /* breaks here */) {
    goto loop;
  }
}

更新:我认为第一个if语句会解决这个问题,因为printf("%f", primes[tested])打印 0。但是,它没有,并且“中断”没有执行。

当代码中断时,tested是 1001。我转换primes[tested]为整数,因为我使用的模算术运算需要整数才能工作。primes[tested]但是,当我从代码打印时,它显示0。如果我从 gdb 打印值,我会得到6.1501785659964211e-319

我错过了什么?我应该修改我的调用realloc以避免此异常吗?

标签: cfloating-pointgdbprimesrealloc

解决方案


我认为第一个if语句会解决这个问题,因为 printf("%f", primes[tested])打印 0。但是,它没有,并且“中断”没有执行。

您测试是否primes[tested] == 0,但您的代码仅在((int)primes[tested]) == 0. 这些根本不是一回事。此外,primes[tested]使用格式打印的值%f并不能可靠地告诉您不同,因为它只给您小数点后的 6 位数字。改为尝试一种"%e"格式,并测试您实际需要的条件,而不是相关的、较弱的条件。

但更好的是,这里不要使用浮点类型。FP 没有用于离散数学问题的业务,例如您似乎试图解决的问题。如果primes[tested]实际上包含素数或可能素数,则unsigned long long int可能具有与 相同的大小double,并且几乎可以肯定可以准确地表示更广泛的素数。或者如果它只包含标志,例如在素数筛中,那么任何比它更宽的东西char都是浪费的。


推荐阅读