这个C循环怎么错了,错在哪里?




#include
int main()
{
    int i,n;
    double sum; 
    sum = 1.0;
    n = 1;
    
    for(n=1;n<=1000;n++)
        if(n%2==0)
        {
        i=1;
        sum = sum + (i)*1.0/(n*n+1);}
        else {
        i =-1;
        sum = sum + (i)*1.0/(n*n+1);}
        
    printf("和为:%f",sum);    
    return 0;
} 

这个代码运行时,当我用n<=1000,结果是0.636。但用n<=1000000时就是1.636怎么回事,不应该一直在0.636附近吗

将分母变成double即可,代码如下,

int main()
{
    int i,n;
    double sum; 
    sum = 1.0;
    n = 1;
    for(n=1;n<=1000000;n++)
        if(n%2==0)
        {
        i=1;
        sum = sum + (i)*1.0/(1.0*n*n+1);}
        else {
        i =-1;
        sum = sum + (i)*1.0/(1.0*n*n+1);}
    printf("和为:%f",sum);    
    return 0;
} 

这个问题应该是数据的范围问题导致的。n<=1000000,应该是15.636,n<=100000才是1.636。
因为在下面的这些数中,n=左边这列数据的时候,1.0/(n*n+1)=1.0了的。而这些数据全是偶数,满足循环体中的if条件,所以对sum来说全是加,每遇到一个这数字sum就会加1。最终结果就是你看到的那样。这个是计算机对数据的存储问题导致的。
65536 1.000000
131072 1.000000
196608 1.000000
262144 1.000000
327680 1.000000
393216 1.000000
458752 1.000000
524288 1.000000
589824 1.000000
655360 1.000000
720896 1.000000
786432 1.000000
851968 1.000000
917504 1.000000
983040 1.000000

基于这种情况,你这个极限求出来误差其实很大,除了以上等于1的几个数据。还有其他超出数据范围的误差也很大,比如:65537,应该接近0的,但实际上是0.000008。
65536 1.000000
65537 0.000008
还有65535,本为奇数,按你的逻辑应该用sum减,但65535计算结果是-0.000008,是个负数,虽用了减法,但最终结果却是sum加。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7794466
  • 除此之外, 这篇博客: 6-4 快速排序中的 本题要求实现快速排序的一趟划分函数,待排序列的长度1<=n<=1000。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    函数接口定义:

    int Partition ( SqList L,int low, int high );
    其中L是待排序表,使排序后的数据从小到大排列。

    类型定义:

    typedef int KeyType;
    typedef struct {
    KeyType *elem; /elem[0]一般作哨兵或缓冲区/
    int Length;
    }SqList;
    裁判测试程序样例:

    #include<stdio.h>
    #include<stdlib.h>
    typedef int KeyType;
    typedef struct {
    KeyType *elem; /elem[0]一般作哨兵或缓冲区/
    int Length;
    }SqList;
    void CreatSqList(SqList *L);/待排序列建立,由裁判实现,细节不表/
    int Partition ( SqList L,int low, int high );
    void Qsort ( SqList L,int low, int high );
    int main()
    {
    SqList L;
    int i;
    CreatSqList(&L);
    Qsort(L,1,L.Length);
    for(i=1;i<=L.Length;i++)
    {
    printf("%d ",L.elem[i]);
    }
    return 0;
    }
    void Qsort ( SqList L,int low, int high )
    { int pivotloc;
    if(low<high)
    {
    pivotloc = Partition(L, low, high ) ;
    Qsort (L, low, pivotloc-1) ;
    Qsort (L, pivotloc+1, high );
    }
    }
    /*你的代码将被嵌在这里 */
    输入样例:

    第一行整数表示参与排序的关键字个数。第二行是关键字值 例如:

    10
    5 2 4 1 8 9 10 12 3 6
    输出样例:

    输出由小到大的有序序列,每一个关键字之间由空格隔开,最后一个关键字后有一个空格。

    1 2 3 4 5 6 8 9 10 12
    作者: DS课程组
    单位: 临沂大学
    时间限制: 400 ms
    内存限制: 64 MB
    代码长度限制: 16 KB


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^