Board logo

标题: [其他] 一个c++程序,求指点,送祭扫 [打印本页]

作者: ylara    时间: 2012-11-7 21:26     标题: 一个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 编辑 ]
作者: ffcactus    时间: 2012-11-7 21:34

posted by wap, platform: iPhone

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

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

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

作者: ffcactus    时间: 2012-11-7 22:13

posted by wap, platform: iPhone

你这反转比用if(a==1) a=0; else a=1; 要慢几十倍。而且一般人看不懂。
作者: ffcactus    时间: 2012-11-7 22:16

posted by wap, platform: iPhone

好像整数除整数不会变浮点吧。
作者: yanger    时间: 2012-11-7 22:19

1/a后面都是0了?

[ 本帖最后由 yanger 于 2012-11-7 22:22 编辑 ]
作者: ffcactus    时间: 2012-11-7 22:29

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;
作者: hourousha    时间: 2012-11-7 22:37

费那么多话直接给个程序不得了?
#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;
}
作者: lvcha    时间: 2012-11-7 22:43

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

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

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

话说你的程序是为了不让人读懂么?
这么写太不专业了。
作者: lvcha    时间: 2012-11-7 22:46

前面也不对。

你a和b直接声明double不就得了。干啥int啊。
作者: ylara    时间: 2012-11-7 22:47

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

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

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

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

作者: karsus    时间: 2012-11-7 22:53

引用:
原帖由 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 编辑 ]
作者: lvcha    时间: 2012-11-7 22:55

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

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

这种程序Fortran最擅长,c/c++的话要考虑很多精度误差以及类型转换的问题。
作者: hourousha    时间: 2012-11-7 23:14

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

喷了,和八楼差不多,我不是故意的。

根据楼主的逻辑,稍微改改:

1 楼主的bug,是因为没有在值赋给result之前对其进行强制类型转换操作
2 楼主没有简化逻辑。
3 (1/b)>0.00001 为什么不写成 b > 100000?
4 让自己适应一种编码风格。代码不带空格拧巴在一起看了很难受。
复制内容到剪贴板
代码:
#include <iostream>

int main()
{
        int a, b;
        a = b = 1;
        double result = 0;

        while( a < 1000000) {
                result += (double) b / a;
                a += 2;
                b = -b;

        }
        std::cout <<  4 * result;

        return 0;
}
[ 本帖最后由 tobewind 于 2012-11-8 00:48 编辑 ]
作者: msforza    时间: 2012-11-8 00:56

posted by wap, platform: iPhone

钓鱼贴,楼上所有人好人一生平安
作者: Mozi    时间: 2012-11-8 08:18

for里面放这么多东西, 果然是第一天上手c++.
作者: chenxiao07    时间: 2012-11-8 13:16

其实计算PI用这个方法也不错,不用外部数据类型,也能计算到小数点后面800位呢
复制内容到剪贴板
代码:
int a=10000,b,c=2800,d,e,f[2801],g;  
main() {
for(;b-c;)
    f[b++]=a/5;
for(;d=0,g=c*2;c -=14,printf("%.4d",e+d/a),e=d%a)  
    for(b=c; d+=f[b]*a,f[b]=d%--g,d/=g--,--b; d*=b);
}
[ 本帖最后由 chenxiao07 于 2012-11-8 13:17 编辑 ]
作者: seek    时间: 2012-11-8 23:47

留名..
tg死程在本帖集结。。




欢迎光临 TGFC Lifestyle (http://bbs.tgfcer.com/) Powered by Discuz! 6.0.0