OʻZBEKISTON RESPUBLIKASI OLIY VA O‘RTA MAXSUS TA’LIM VAZIRLIGI
MIRZO ULUG‘BEK NOMIDAGI MILLIY UNIVERSITETININIG JIZZAX FILIALI
AMALIY MATEMATIKA FAKULTETI «Axborot tizimlari va texnologiyasi» kafedrasi
“ALGORITMLAR VA BERILGANLAR STRUKTURASI” FANIDAN
MUSTAQIL ISH 1
Mavzu: Eyler funksiyasi va uni hisoblash algoritmi
Bajardi: “Axborot tizimlari va texnologiyasi” yoʻnalishi 2-kurs guruh 23-21 talabasi Eshpo’latov Javohir
Tekshirdi:Tojiyev.M
Jizzax – 2023
Reja:
1.Eyler funksiyasi.
2.Muammolar.
3.Missollar.
U yana tushuntirganidek, eps bu algoritmning aniqligi. Masalan, aniqlik 1/100 |x_(i + 1) - x_i| = ( x_(i+1) - x_i ) ning mutlaq qiymati
Hozirda mening dasturim quyidagi tarzda ko'rinadi:
#include
#include
#include
// Euler's number
using namespace std;
double factorial(double n)
{
double result = 1;
for(double i = 1; i <= n; i++)
{
result = result*i;
}
return result;
}
int main()
{
long double euler = 2;
long double counter = 2;
long double epsilon = 1.0/1000;
long double moduloDifference;
do
{
euler+= 1 / factorial(counter);
counter++;
moduloDifference = (euler + 1 / factorial(counter+1) - euler);
} while(moduloDifference >= epsilon);
printf("%.35Lf ", euler );
return 0;
}
Muammolar:
Mening epsilon qiymatim to'g'ri ishlamayapti. Bu aniqlikni nazorat qilishi kerak. Misol uchun, men 5 ta raqamning aniqligini xohlasam, uni 1,0/10000 ga ishga tushiraman va u 8 (.7180) dan keyin qisqartirilgunga qadar 3 ta raqamni chiqaradi.
Men uzun qo'shaloq ma'lumot turini ishlatganimda va epsilon = 1/10000, mening epsilonim 0 qiymatini oladi va mening dasturim cheksiz ishlaydi. Shunga qaramay, agar ma'lumotlar turini long doubledan ikki barobarga o'zgartirsangiz, u ishlaydi. Nega uzun ikkilamchi ma'lumot turidan foydalanilganda epsilon 0 ga aylanadi?
Eyler raqamini topish algoritmini qanday optimallashtirishim mumkin? Bilaman, men funktsiyani o'chirib qo'yishim va Eyler qiymatini tezda hisoblashim mumkin, lekin buni amalga oshirishga har bir urinishdan keyin men boshqa xatolarni olaman.
1. nima uchun faktorial? Siz 1, 1*2, 1*2*3, 1*2*3*4 ... hisoblayotganingizni bilasiz, shuning uchun nima uchun oxirgi natijadan foydalanmaysiz va uni i ga ko'paytirasiz? 2. Jerri Koffinning javobi katta va kichik qiymatlarni qo'shish ishlamaydi ... u tartibni teskari o'zgartirishni taklif qiladi, lekin oldinda n ni bilmasdan yoki "cheksiz" xotiraga ega bo'lmasdan bu mumkin emas. Buning o'rniga siz quyi natijani katta va kichik kattaliklarga bo'lishingiz kerak, men bu erda qilganimdek, [tahrirlash1] integratsiya aniqligini qidiring -
Spektr
2021-yil 13-yanvar, soat 9:11
Agar siz tenglamaga bog'lanmagan bo'lsangiz, e = (1+1/x) ^ x dan foydalangan holda ikkilik kompyuterlarda e ni hisoblash uchun yaxshiroq mos keladigan usul mavjud vazifalar bilan Eyler raqamiga qarang ... aniqlik faqat funktsiyadir. log(aniqlik)/log(2) dan hisoblanishi mumkin bo'lgan bitlar ... ammo bu endi farqni tekshirishni talab qilmaydi, shuning uchun agar bu topshiriq bo'lsa, bu to'g'ri uy vazifasi deb hisoblanmaydi ... –
Spektr
2021-yil 13-yanvar, soat 9:15
1
@Secundi ha, butun son/float o'rtasida hech qanday casting yoki yaxlitlash sodir bo'lmasligiga ishonch hosil qilish uchun barcha suzuvchi literallarga .0 qo'shgan bo'lardim ... Men bu narsa haqida biroz paranoyakman, chunki men kompilyatorlar (vaqti-vaqti bilan) bilan shug'ullanaman. 1/2,5 butun son arifmetikasiga qisqartiriladi va keyin suzuvchi holatga qaytariladi, bu esa narsalarni noaniq va sekinlashtiradi ... –
Spektr
2021-yil 13-yanvar, soat 9:40
1
@max, iltimos, savolingizni bu erda yangilang, chunki deyarli takrorlangan savolingiz allaqachon u erda, ayniqsa optimallashtirish nuqtai nazaridan foydali javoblarni olgan. Ehtimol, asl savol takrorlangan deb belgilanishi kerak. -
Sekundi
2021-yil 13-yanvar, soat 10:54
3
Eyler konstantasini shu tarzda hisoblash bilan bog'liq muammolardan biri juda oddiy: siz juda katta raqamlardan boshlayapsiz, lekin har bir atamadagi maxraj N! bo'lgani uchun, har bir keyingi atama qo'shadigan miqdor juda tez qisqaradi. Oddiy yig'indidan foydalanib, siz tezda qo'shayotgan qiymat yig'indiga ta'sir qilmaydigan darajada kichik bo'lgan nuqtaga erishasiz.
Eyler konstantasining o'ziga xos holatida, raqamlar doimiy ravishda kamayib borayotganligi sababli, biz ular bilan yaxshiroq muomala qilishning bir usuli - barcha shartlarni hisoblash va saqlash, keyin ularni teskari tartibda qo'shish.
Umumiyroq bo'lgan yana bir imkoniyat bu o'rniga Kahanning yig'ish algoritmidan foydalanishdir. Bu yig'indini bajarayotganda ishlayotgan xatoni kuzatib boradi va har bir keyingi atamani qo'shishda joriy xatoni hisobga oladi.
Misol uchun, men sizning kodingizni odatdagi (80-bit) uzunlikdagi dublning aniqlik chegarasiga (taxminan) hisoblash uchun Kahan yig'indisidan foydalanish uchun qayta yozdim:
#include
#include
#include
#include
#include
#include
// Euler's number
using namespace std;
long double factorial(long double n)
{
long double result = 1.0L;
for(int i = 1; i <= n; i++)
{
result = result*i;
}
return result;
}
template
typename std::iterator_traits::value_type accumulate(InIt begin, InIt end) {
typedef typename std::iterator_traits::value_type real;
real sum = real();
real running_error = real();
for ( ; begin != end; ++begin) {
real difference = *begin - running_error;
real temp = sum + difference;
running_error = (temp - sum) - difference;
sum = temp;
}
return sum;
}
int main()
{
std::vector terms;
long double epsilon = 1e-19;
long double i = 0;
double term;
for (int i=0; (term=1.0L/factorial(i)) >= epsilon; i++)
terms.push_back(term);
int width = std::numeric_limits::digits10;
std::cout << std::setw(width) << std::setprecision(width) << accumulate(terms.begin(), terms.end()) << "\n";
}
Result: 2.71828182845904522
In fairness, I should actually add that I haven't checked what happens with your code using naive summation--it's possible the problem you're seeing is from some other source. On the other hand, this does fit fairly well with a type of situation where Kahan summation stands at least a reasonable chance of improving results.
#include
#include
#include
#define EPSILON 1.0/10000000
#define AMOUNT 6
using namespace std;
int main() {
long double e = 2.0, e0;
long double factorial = 1;
int counter = 2;
long double moduloDifference;
do {
e0 = e;
factorial *= counter++;
e += 1.0 / factorial;
moduloDifference = fabs(e - e0);
} while (moduloDifference >= EPSILON);
cout << "Wynik:" << endl;
cout << setprecision(AMOUNT) << e << endl;
return 0;
}
Dostları ilə paylaş: |