当前位置:编程学习 > C/C++ >>

非常令人困惑的一个C++程序

程序如下:

#include<iostream>
#include<cmath>
#include<fstream>
#define max 10000
using namespace std;
int main()
{
 int N;       /*  定义相关变量及数组  */
 double w[max][3]={0};
 double k[2][5]={0}; /*  存放斜率的数组,行代表方程标号,列代表每一个方程的四个斜率 */
 double f1(double t,double y1,double y2);
 double f2(double t,double y1,double y2);
   
 double a,b;
 cout<<"请从小到大依次输入区间的上下界:\n"<<endl;/*  输入相关参数  */
 cin>>a>>b;
 cout<<"你想把区间划分成多少分呢?请输入:\n"<<endl;
 cin>>N;
 double h=(b-a)/N;
 cout<<"步长 h="<<h<<endl;

    w[0][0]=-0.4000;    /*    在循环之前,先对各变量初始化  */
 w[0][1]=-0.6000;    /*    存放近似数值解的数组,行代表迭代次数,列代表方程的个数    */

   
 for(int i=1;i<N;i++)  /*  控制迭代次数  */
 {
  for(int j=0;j<2;j++)
  {

   k[1][1]=h*f1(a+(i-1)*h,w[i-1][0],w[i-1][1]);   /*  行表示方程标号,列表示每个方程k的标号  */
   k[2][1]=h*f2(a+(i-1)*h,w[i-1][0],w[i-1][1]);
        
   k[1][2]=h*f1(a+(i-10)*h+h/2.0,w[i-1][0]+1.0/2*k[1][1],w[i-1][1]+1.0/2*k[2][1]);
   k[2][2]=h*f2(a+(i-1)*h+h/2.0,w[i-1][0]+1.0/2*k[1][1],w[i-1][2]+1.0/2*k[2][1]);

   k[1][3]=h*f1(a+(i-1)*h+h/2.0,w[i-1][0]+1.0/2*k[1][2],w[i-1][2]+1.0/2*k[2][2]);
   k[2][3]=h*f2(a+(i-1)*h+h/2.0,w[i-1][0]+1.0/2*k[1][2],w[i-1][2]+1.0/2*k[2][2]);

   k[1][4]=h*f1(a+(i-1)*h+h,w[i-1][1]+1.0/2*k[1][3],w[i-1][2]+1.0/2*k[2][3]);
   k[2][4]=h*f2(a+(i-1)*h+h,w[i-1][1]+1.0/2*k[1][3],w[i-1][2]+1.0/2*k[2][3]);
        
   w[i][0]=w[i-1][0]+1.0/6*(k[1][1]+2*k[1][2]+2*k[1][3]+k[1][4]);
   w[i][1]=w[i-1][0]+1.0/6*(k[2][1]+2*k[2][2]+2*k[2][3]+k[2][4]);
  }
 }

 for(int m=0;m<N;m++)
  cout<<w[m][0]<<" "<<w[m][1]<<endl;

 

 

 return 0;
}

  double f1(double t,double y1,double y2)
  {
   return y2;
  }

  double f2(double t,double y1,double y2)
  {
   return (exp(2*t)-2*y1+2*y2);
  }

    我单步运行程序观察变量值的变化,一开始用 w[0][1]=-0.6000;给数组元素赋值,但是竟然发现w[0][1]自己无缘无故变成了0.06,这太让人困惑了,因为我反复检查程序,我并没有改变w[0][1]的值啊,为什么它竟然会自己改变值呢?

    附上截图:

 

截图中w[0][1]=0.060000000000012,真是百思不得其解,我明明给它赋的值是w[0][1]=-0.6000啊,盼望大侠来指教一下

 

 


  
   

追问:来自手机问问就算是不准可是难道-0.6在内存中是以0.06存储的吗?我对这个了解不是太多,还请多指点指点
答案:原因很简单:数组越界。请注意你的for内层循环中的第二句k[2][1]=h*f2(a+(i-1)*h,w[i-1][0],w[i-1][1]);数组k定义的时候为2行5列,下标从0开始,也就是你最多能引用k[1][4],可是你却引用了k[2][1],而这个k[2][1]恰巧就是w[0][1](这是因为内存分配的时候从高地址向低地址增长,假设分配给w[0][0]的地址是addr,则分配给k[0][0]的地址就是addr-2*5*8=addr-80,其中2和5是k的行列数,8是一个double型数据的字节数,虽然k[2][1]是不合法的,但仍然可以按规则计算它的地址:addr-80+(2*5+1)*8=addr+8,这恰好是w[0][1]的地址)。换句话说,你在for循环里面修改k[2][1]的值就等于修改了w[0][1]的值,所以在你的程序中从0.6变成了-0.6,事实上它变成任何数都不奇怪;不止如此,你引用的k[2][2]、k[2][3]、k[2][4]都不合法,它们分别相当于w[0][2]、w[0][3]、w[0][4]的值,你可以查看一下,这几个值在for循环之后都不再是初始化的0。相信解决方法你应该清楚了吧,把引用k数组的第一维下标全部减1就行了。C/C++语言本身不检查数组越界这一点请务必格外注意。

有这种情况有几种可能:
1、有可能出现了内存溢出(我也发生过类似的问题),请检查一下有没有内存溢出。
2、可能还有什么地方改了没发现(其实我也没发现)。
3、你可以尝试把中间那一段代码注释掉,然后再看看w[0][1]得知有没有改变。
4、更多请加我Q:875053761
呵呵,看看浮点数的存储方式吧.浮点数是不准的,所以一般的程序都不会直接比较两个浮点数,而是比较到某个精度.比如 A B两个浮点数差值小于0.000001(当然这个数度看你的要求))就认为它们相等.

上一个:麻烦大家推荐本二级C++的教材
下一个:用c++怎样才能生成. exe文件

CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,