Често срещани грешки в C++

от Moby Dick на 05 август 2009, 10:43

Категории: Програмиране
Етикети: инициализация на променливи

 

     Бих желал да допренеса с нещо за по-доброто разбиране на езика C++. В следващите няколко реда се описват няколко често срещани грешки.

    При деклариране на променлива от хардуерен тип в RAM паметта се заделя определенo количество байта памет. В езика C++ програмистът трябва да инициализира, установи началната стойност на новата променлива. Оттук произлиза и една от най-често срещаните грешки: неверен резултат при натрупване на сума (началната стойност трябва да е 0) и/или произведение (началната стойност трябва да е 1).

    Почти със същата честота на срещане е грешката от прехвърляне на допустимите стойности за даден хардуерен тип променлива. Тук такава грешка би могла да възникне при много на брой променливи или въведени големи стойности за тях. Затова и произведението им в задачата ще бъде променлива от типа unsigned long. Справедливостта изисква и известно уточнение типа unsigned long long  ще е коректен само, ако всички въвеждани стойности са >0.

    Друга, макар и с по-малка честота, е грешката за изчисляване на съотношение, когато числителят и/или знаменателят се формират като суми/произведения.

     Нека разгледаме следната задача:

Дадена е числова редица от N естествени числа, които не са непременно различни и са  от интервала [1..101]. Да се състави програма, чрез която се извежда сумата от реципрочните стойности на участващите в редицата числа.

Практическият смисъл на програмата е изчисляване на еквивалентното съпротивление от N паралелно свързани резистори от една електрическа верига.

Най-лесният, но и не особено верен алгоритъм, е да се сумират реципрочните стойности на отделните елементи. Всеки от типовете float, double съхранява стойността с известно закръгление. Така грешката от закръгление ще се натрупва с всяко следващо събираемо.

Формулата за 2 елемента би изглеждала така:

1) 1/r1  + 1/r2 = r1*r2 / (r1+r2)

за 3 елемента би изглеждала така:

2) 1/r1 + 1/r2 +1/r3 = r1*r2*r3/ (r2*r3 +r1*r3 +r1*r2))

Описанието за N елемента е:

Числителят е равен на произведението от всички N елементи в редицата;

Знаменателят е равен на сумата от N на брой произведения, във всяко от които участват всички N елемента, но стойността на поредният номер елемент е заменена с 1 в произведението със същия пореден номер.

 

Следва source code на програмата - за DEV C++

 

#include <iostream>

using namespace std;

 

unsigned long proizw(int mas[], int nom, int br)

{unsigned long rez;

 int j;

 rez=1;//nachalna inicializaciq za natrupwane na proizwedenie

 for (j=0;j<br;j++)

  { if (j!=nom) rez*=mas[j]; 

  }//for

 return rez;

 }//proizw

 

 double rezist(int mas[], int br)

 {int i,k;

 unsigned long chis, znam, sum; 

  double rezi;

  k=br;

sum=0;//inicializaciq na suma

  chis=proizw(mas,k+1,k);//da naprawi obshoto proizwedenie

  cout<<"Chislitel: "<<chis<<endl;

  for (i=0;i<k;i++)

   { znam=proizw(mas,i,k);//poredniq chlen w sumata ot proizwedeniq

    cout<<"Cheln ot znamenatelq s nomer: "<<i+1<<" = "<<znam<<endl;

    sum+=znam;   

  }//for   

  cout<<"Suma na znamenatelq: "<<sum<<endl; 

  rezi=(double)chis/sum;//

  return rezi;

}       

 

int main()

{ const int br=4;//broj rezistori

 int mas[br]={5,4,3,6};//stojnosti na rezistorite

double rez;

cout<<"Imate predwaritelno wywedeni stojnosti za syprotiwlenie na N broq \n";

cout<<"rezistori. Trqbwa da se izchisli ekwiwalentnoto im syprotiwlenie\n";

cout<<"pri paralelno swyrzwane na rezistorite.\n";

cout<<"Primer: 10,10,10,10 Izhod: 2.5\n";

cout<<"Drug primer: 5,4,3,6\n";

rez=rezist( mas, br);

cout<<"Ekwiwalentnoto syprotiwlenie e: "<<rez<<endl;

system ("pause");//izchakwa natiskane na klawish

return 0;

}

 Примерната програма е част от електронните уроци на адрес www.rbukvar.eu