» 您尚未登录:请 登录 | 注册 | 标签 | 帮助 | 小黑屋 |


 20 12
发新话题
打印

[其他] 一个c++程序,求指点,送祭扫

利用格里高利公式编写程序求π。
                π/4=1-1/3+1/5-1/7+……
直到最后一项的值小于10-6为止。

#include <iostream.h>
void main()
{
        int a,b,i;
        double x=0;
        for (a=1,b=1,i=0; (1/b)>0.00001; b=b+2,a=b*(-1)^i,i++)
        {
                x=x+1/a;
        }       
        cout<<x;
}
我是这样想的, (1/b)>0.00001用来控制精度,因为b恒正。
b=b+2,a=b*(-1)^i,i++。这句用来控制a的变化是1,-3,5,-7.。。。
然后做x,感觉挺对的,但是输出结果是1,。
刚学,求指导。

[ 本帖最后由 ylara 于 2012-11-7 22:07 编辑 ]


TOP

posted by wap, platform: iPhone

首先你的程序不直观。for 寻坏最好用一个步进2的整数记数器,同时用作分母。循环中设置加减符号反转变量。这样你也无需考虑正负就能得到循环退出的条件。
这样写的程序别人知道这个公式的话,看你程序就知道你在干嘛。



本帖最近评分记录
  • ylara 激骚 +1 精品文章 2012-11-7 22:12

TOP

我这里的加减反转变量就是(-1)^i,i++啊
引用:
原帖由 ffcactus 于 2012-11-7 21:34 发表
posted by wap, platform: iPhone

首先你的程序不直观。for 寻坏最好用一个步进2的整数记数器,同时用作分母。循环中设置加减符号反转变量。这样你也无需考虑正负就能得到循环退出的条件。
这样写的程序别人知道这 ...


TOP

posted by wap, platform: iPhone

你这反转比用if(a==1) a=0; else a=1; 要慢几十倍。而且一般人看不懂。

TOP

posted by wap, platform: iPhone

好像整数除整数不会变浮点吧。

TOP

1/a后面都是0了?

[ 本帖最后由 yanger 于 2012-11-7 22:22 编辑 ]

TOP

posted by wap, platform: iPhone

Double x=0;
for(long a=1, int f=0; a < 100000; a+=2) {
   if(f++ == 0)
       x+= ( 1.0f / a );
   else {
      f--;
      x-= ( 1.0f / a );
   }
}

Cout << x *4 << endl;

TOP

费那么多话直接给个程序不得了?
#include <iostream>
void main()
{
        double denominator = 1.0;
        double pi=0.0;
        double signflag = 1.0;
        while(denominator<=100000.0)
        {
                 pi += signflag/denominator;
                 denominator += 2.0;
                 signflag *= -1.0;
        }
        pi *= 4.0;
        std::cout<<pi<<std::endl;
}
本帖最近评分记录
  • ylara 激骚 +4 我很赞同 2012-11-7 22:45

TOP

a是int,除了1分之一是1以外其它都是0啊

不好意思c++还是中学课外班学的早忘了。

按java来说你 改成 x+1.0/(double)a就好了

话说你的程序是为了不让人读懂么?
这么写太不专业了。

TOP

前面也不对。

你a和b直接声明double不就得了。干啥int啊。

TOP

。。。我的错我的错
引用:
原帖由 lvcha 于 2012-11-7 22:43 发表
a是int,除了1分之一是1以外其它都是0啊

不好意思c++还是中学课外班学的早忘了。

按java来说你 改成 x+1.0/(double)a就好了

话说你的程序是为了不让人读懂么?
这么写太不专业了。

TOP

引用:
原帖由 hourousha 于 2012-11-7 22:37 发表
费那么多话直接给个程序不得了?
#include
void main()
{
        double denominator = 1.0;
        double pi=0.0;
        double signflag = 1.0;
        while(denominator
signflag 和denominator定义的时候需要用Int,运算中强转成double,不然连续相加和相乘有浮点误差

看错

[ 本帖最后由 karsus 于 2012-11-7 22:57 编辑 ]

TOP

引用:
原帖由 karsus 于 2012-11-7 22:53 发表

signflag 和denominator定义的时候需要用Int,运算中强转成double,不然连续相加和相乘有浮点误差
这样啊,java里加个strictfp关键字就好了。

TOP

这种程序Fortran最擅长,c/c++的话要考虑很多精度误差以及类型转换的问题。

TOP

引用:
原帖由 karsus 于 2012-11-7 22:53 发表
signflag 和denominator定义的时候需要用Int,运算中强转成double,不然连续相加和相乘有浮点误差
signflag完全没必要做这种处理。因为-1.0的寄存器内存储形式是0xBFF0000000000000,而1.0的存储是0x3FF0000000000000,根据浮点乘法运算的原理,无论乘多少次也不会出岔子的。
浮点容易出问题的是在加减法,因为存在指数位对齐操作导致的尾数位移位操作。因此从理论上denominator做你说的操作并非完全无用,不过实际上那种累计式误差,主要存在于对一个变量的连续迭代上,像这种只是以常数值递增的情况,误差是可以忽略的。尤其是它的值并不很大的情况。
其实就一般习惯来说,只要注意别对浮点数使用==来判断也就差不多了。
如果要做高精度运算,一般都是不是用浮点数来做的。当然LZ这个公式的收敛速度之慢也不是高精度计算pi用的公式。
本帖最近评分记录
  • ylara 激骚 +1 最骚 Rated by wap 2012-11-12 21:35
  • ylara 激骚 +1 最骚 Rated by wap 2012-11-12 21:35

TOP

 20 12
发新话题
     
官方公众号及微博