【问题标题】:Pi-calculator program gives different output each time it's runPi计算器程序每次运行时都会给出不同的输出
【发布时间】:2017-12-20 15:07:34
【问题描述】:

这是一个使用“任意两个整数互质的概率是 6/π2”这一事实来计算 Pi 值的程序。这个程序编译成功,但是当我尝试运行它时,它给出了错误:

Segmentation fault (core dumped)

我试图将 for 循环中的条件语句更改为 i 。通过这样做,程序给出的输出(每次运行时)在 3.000000、3.162278 和分段错误(核心转储)之间变化。

我只想使用上面提到的属性来计算 π 的值。请帮忙。

另外,请帮助我选择一个更好的函数来生成随机数并建议我进行一些代码改进。谢谢。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

int gcd(int a, int b)
{
    // Everything divides 0 
    if (a == 0 || b == 0)
       return 0;

    // base case
    if (a == b)
        return a;

    // a is greater
    if (a > b)
        return gcd(a-b, b);
    return gcd(a, b-a);
}

int main()
{
    srand(time(0));

    int numberOne = rand();
    int numberTwo = rand();
    int coprime = 0;

    for(int i = 0; i < 99999; i++)
    {
        numberOne = rand();
        numberTwo = rand();

        if(gcd(numberOne, numberTwo) == 1)
        {
            coprime++;
        }

    }

    // co-prime/99999 = 6 / pi^2
    double pi = 599994/coprime;
    pi = sqrt(pi);

    printf("%f\n", pi);

    return 0;
}

【问题讨论】:

  • 我猜?当您认为它停止时,您的递归不会停止。您是否尝试过使用调试器来捕捉崩溃并查看它发生的时间和地点?也许你应该花点时间来learn how to debug your programs
  • 您的 gdc 函数导致堆栈溢出。这意味着您缺少退出条件
  • 每次运行您的代码时我都会得到“3.000000”
  • 替换双 pi = 599994/coprime; by double pi = 599994.0/static_cast(coprime);您可能会从整数除法中丢失一些数字。
  • @falopsy 只要操作数之一是double,就不需要强制转换。

标签: c++ c random segmentation-fault pi


【解决方案1】:

OP 的gcd() 递归太深并导致堆栈溢出@OldProgrammer

考虑一个更高效的替换递归函数

在进行除法时使用 FP 数学

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

unsigned gcdu(unsigned a, unsigned b) {
  return (b == 0) ? a : gcdu(b, a % b);
}

int main(void) {
  srand(time(0));

  int numberOne = rand();
  int numberTwo = rand();
  int coprime = 0;

  for (int i = 0; i < 99999; i++) {
    numberOne = rand();
    numberTwo = rand();
    if (gcdu(numberOne, numberTwo) == 1) {
      coprime++;
    }
  }

  // double pi = 599994 / coprime;
  double pi = 1.0*599994 / coprime;  //Insure FP division
  pi = sqrt(pi);
  printf("%f\n", pi);
  return 0;
}

输出

3.142940

【讨论】:

  • FWIW,用gcdu(774542945, 2027634402) 记录了 39 的高递归深度。使用OP的原始代码,深度可能是千百万gcd(1000000000,1)
  • gcdu(1276900689, 2066068658) 递归了 41 次。嗯,不知道限制是多少?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
  • 1970-01-01
  • 2021-10-17
  • 1970-01-01
相关资源
最近更新 更多