আমি কিছুক্ষণ আগে একটি কোড লিখেছিলাম যা লাইব্রেরির ফাংশন ব্যবহার না করেই গণনা করার চেষ্টা করেছিল । গতকাল, আমি পুরানো কোডটি পর্যালোচনা করছিলাম, এবং আমি এটি যথাসম্ভব দ্রুত করার চেষ্টা করেছি (এবং সঠিক)। এখানে এখন পর্যন্ত আমার প্রচেষ্টা:
const double ee = exp(1);
double series_ln_taylor(double n){ /* n = e^a * b, where a is an non-negative integer */
double lgVal = 0, term, now;
int i, flag = 1;
if ( n <= 0 ) return 1e-300;
if ( n * ee < 1 )
n = 1.0 / n, flag = -1; /* for extremely small n, use e^-x = 1/n */
for ( term = 1; term < n ; term *= ee, lgVal++ );
n /= term;
/* log(1 - x) = -x - x**2/2 - x**3/3... */
n = 1 - n;
now = term = n;
for ( i = 1 ; ; ){
lgVal -= now;
term *= n;
now = term / ++i;
if ( now < 1e-17 ) break;
}
if ( flag == -1 ) lgVal = -lgVal;
return lgVal;
}
এখানে আমি এমন করার চেষ্টা করছি যাতে ই ক কেবলমাত্র এন এর উপরে, এবং তারপরে আমি n এর লগারিদম মান যুক্ত করব
আমি সম্প্রতি সংখ্যার বিশ্লেষণে আগ্রহ বাড়িয়েছি এবং সে কারণেই আমি এই প্রশ্নটি জিজ্ঞাসা করতে সহায়তা করতে পারি না, যথেষ্ট সংখ্যক সঠিক হওয়ার পরেও এই কোড বিভাগটি অনুশীলনে কতটা দ্রুত চালানো যেতে পারে? আমার কি অন্য কিছু পদ্ধতিতে স্যুইচ করা দরকার, উদাহরণস্বরূপ, এভাবে চালিয়ে যাওয়া ভগ্নাংশ ব্যবহার করে ?
আপডেট 1 : উইকিপিডিয়ায় উল্লিখিত হাইপারবোলিক আর্টিকান সিরিজটি ব্যবহার করে, গণনাটি সি স্ট্যান্ডার্ড লাইব্রেরি লগ ফাংশনের চেয়ে প্রায় 2.2 গুণ ধীর বলে মনে হচ্ছে। যদিও, আমি কার্যকারিতাটি ব্যাপকভাবে পরীক্ষা করে দেখিনি, এবং বৃহত্তর সংখ্যার জন্য, আমার বর্তমান বাস্তবায়ন সত্যিই ধীর বলে মনে হচ্ছে। আমি যদি পরিচালনা করতে পারি তবে বিস্তৃত সংখ্যার জন্য ত্রুটিযুক্ত এবং গড় সময়ের জন্য আমার বাস্তবায়ন দুটিই পরীক্ষা করতে চাই। এখানে আমার দ্বিতীয় প্রচেষ্টা।
double series_ln_arctanh(double n){ /* n = e^a * b, where a is an non-negative integer */
double lgVal = 0, term, now, sm;
int i, flag = 1;
if ( n <= 0 ) return 1e-300;
if ( n * ee < 1 ) n = 1.0 / n, flag = -1; /* for extremely small n, use e^-x = 1/n */
for ( term = 1; term < n ; term *= ee, lgVal++ );
n /= term;
/* log(x) = 2 arctanh((x-1)/(x+1)) */
n = (1 - n)/(n + 1);
now = term = n;
n *= n;
sm = 0;
for ( i = 3 ; ; i += 2 ){
sm += now;
term *= n;
now = term / i;
if ( now < 1e-17 ) break;
}
lgVal -= 2*sm;
if ( flag == -1 ) lgVal = -lgVal;
return lgVal;
}
কোন পরামর্শ বা সমালোচনা প্রশংসা করা হয়।
double series_ln_better(double n){ /* n = e^a * b, where a is an non-negative integer */
double lgVal = 0, term, now, sm;
int i, flag = 1;
if ( n == 0 ) return -1./0.; /* -inf */
if ( n < 0 ) return 0./0.; /* NaN*/
if ( n < 1 ) n = 1.0 / n, flag = -1; /* for extremely small n, use e^-x = 1/n */
/* the cutoff iteration is 650, as over e**650, term multiplication would
overflow. For larger numbers, the loop dominates the arctanh approximation
loop (with having 13-15 iterations on average for tested numbers so far */
for ( term = 1; term < n && lgVal < 650 ; term *= ee, lgVal++ );
if ( lgVal == 650 ){
n /= term;
for ( term = 1 ; term < n ; term *= ee, lgVal++ );
}
n /= term;
/* log(x) = 2 arctanh((x-1)/(x+1)) */
n = (1 - n)/(n + 1);
now = term = n;
n *= n;
sm = 0;
/* limiting the iteration for worst case scenario, maximum 24 iteration */
for ( i = 3 ; i < 50 ; i += 2 ){
sm += now;
term *= n;
now = term / i;
if ( now < 1e-17 ) break;
}
lgVal -= 2*sm;
if ( flag == -1 ) lgVal = -lgVal;
return lgVal;
}