【问题标题】:Why I am getting floating point exception为什么我得到浮点异常
【发布时间】:2019-09-29 19:14:16
【问题描述】:

我认为我的代码中没有任何一点我达到零或将其除以零所以任何人都可以帮助我为什么输入 20 75 会出现浮点异常

我只是计算 2*n -1 的阶乘,然后用 n 和 n-1 的阶乘来计算它,但我不知道我的代码在哪里变为零或其他原因

int fact(int num) {
    if(num == 1 || num == 0) return 1;
    else return (num*fact(num-1));
}
int Solution::solve(int A) {
    int val1 = fact(A-1);
    int val2 = fact(A-1+A-1);
    int ans = (val2/((val1*val1)%1000000007))%1000000007;
    return (ans/A)%1000000007;
}

对于 A = 20 或 A = 75,我得到浮点异常

【问题讨论】:

  • 因为在过去名称非常有限,整数除以零会触发浮点异常。 (val1*val1)%1000000007) can resolve to 0, so (val2/((val1*val1)%1000000007))`可以去BOOOOM!
  • 谢谢,我喜欢你对解决方案的看法,这是一种非常聪明的方法,我也希望它能奏效,但不幸的是我仍然面临浮点异常
  • "我不认为..." - 当我到了那个时候,我会拿出调试器。

标签: c++ floating-point


【解决方案1】:

输入 A = 20,您调用 fact(20 - 1)fact(20 - 1 + 20 - 1),它们是 fact(19) fact(38)。 19 的阶乘是 121645100408832000,38 的阶乘是 523022617466601111760007224100074291200000000。

在典型的 PC 上,int 的最大可表示值为 2147483647,它小于您尝试计算的上述任何一个阶乘。您的程序溢出有符号整数,程序的行为未定义。

我认为我的代码中没有任何意义...除以零

(val1*val1)%1000000007 对于val1 的某些值可能为零。因此val2/((val1*val1)%1000000007) 可能被零除。一个简单的情况是val1 为零,而另一种情况是 1000000007。您可能认为val1 永远不可能是这些值中的任何一个,因为它们不是阶乘,但它完全可以是当您在程序中签名溢出时的任一值。

用 32 位整数表示的最大阶乘是 12!因此,您的函数可以解决的最大输入是 A = 7。

【讨论】:

  • 就算是13的计算!将溢出一个 32 位有符号整数。所以fact(A-1) 的计算会给A 14 或更多的未定义行为。
  • 感谢@Peter 的帮助,现在我已经修改了我的代码并使其如下所示,int fact(int num) { if(num == 1 || num == 0) return 1;否则返回 (num*(fact(num-1)%1000000007))%1000000007; } int 解决方案::solve(int A) { int val1 = fact(A-1); int val2 = 事实(A-1+A-1)%1000000007; int ans = (val2/((val1*val1)%1000000007)); cout
  • 我所做的是在获取阶乘的同时添加 %1000000007,使其保持在 int 范围内,但我仍然遇到异常行为
  • @ParikshitSingh - 当fact() 函数中发生溢出时发生未定义行为 - 换句话说,在val1val2 的计算中。随后计算 (val1*val1)%1000000007 并不能神奇地解决这个问题。
【解决方案2】:

我不能添加太多,但如果您将所有 int var = ... 变量更改为 long long int var = ... (虽然我认为根据 Google 的样式指南,不建议使用 long long int)它也可以与 20 的输入一起使用,因为其中提到的原因 以前的cmets:

long long int fact(long long int num) {
    if(num == 1 || num == 0) return 1;
    else return (num*fact(num-1));
}
int Solution::solve(int A) {
    long long int val1 = fact(A-1);
    long long int val2 = fact(A-1+A-1);
    long long int ans = (val2/((val1*val1)%1000000007))%1000000007;
    return (ans/A)%1000000007;
}

【讨论】:

  • 用 64 位整数签名的最大输入可解是 A = 11。
猜你喜欢
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 2012-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多