সি / সি ++ এ লগ বেস (2) কীভাবে লিখবেন


99

লগ (বেস 2) ফাংশন লিখতে কোন উপায় আছে?

সি ভাষার 2 টি কার্যত বিল্ট রয়েছে - >>

1. logযা বেস ই।

2. log10বেস 10;

তবে এটি হিসাব করার জন্য আমার বেস 2 এর লগ ফাংশন প্রয়োজন।


4
চোখের বলের গণনার জন্য, বেস 2 লোগারিদম বেস 10 লোগারিদম প্লাস প্রাকৃতিক লোগারিদমের সমান। অবশ্যই কোনও প্রোগ্রামে আরও নির্ভুল (এবং দ্রুত) সংস্করণ লেখা ভাল write
ডেভিড থর্নলে

পূর্ণসংখ্যার জন্য, আপনি ডান বিটশিফ্টে লুপ করতে পারবেন এবং 0 এ পৌঁছলে থামতে পারবেন লুপের গণনাটি লগের একটি অনুমান
বেসাইল স্টারিনকিভিচ

উত্তর:


202

সাধারণ গণিত:

    লগ 2 ( x ) = লগ y ( এক্স ) / লগ ওয় (2)

যেখানে y যে কোনও কিছু হতে পারে, যা স্ট্যান্ডার্ড লগ ফাংশনগুলির জন্য হয় 10 বা



53

আপনি যদি একটি অবিচ্ছেদ্য ফলাফল খুঁজছেন, আপনি কেবলমাত্র মান সর্বাধিক বিট সেট নির্ধারণ করতে এবং তার অবস্থান ফিরে করতে পারেন।


27
এর জন্য একটি দুর্দান্ত বিট-টুইডলিং পদ্ধতি রয়েছে (জাভা Integer.highestOneBit(int)পদ্ধতি থেকে নেওয়া ):i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); return i - (i >>> 1);
জো

39
... বাwhile (i >>= 1) { ++l; }
লি ড্যানিয়েল ক্রকার

4
@ জোয় এটি অনুমান করে কাজ করবে যে 32 বিট প্রশস্ত, না? Bit৪ বিটের জন্য এটির অতিরিক্ত লাগবে i>>32। তবে যেহেতু জাভাতে কেবল 32-বিট ইনট রয়েছে, এটি ঠিক আছে। সি / সি ++ এর জন্য এটি বিবেচনা করা দরকার।
জোসো

43
#define M_LOG2E 1.44269504088896340736 // log2(e)

inline long double log2(const long double x){
    return log(x) * M_LOG2E;
}

(গুণটি বিভাগের চেয়ে দ্রুততর হতে পারে)


4
কেবল স্পষ্ট করতে চেয়েছিলেন - লগ রূপান্তর নিয়ম ব্যবহার করে + লগ_2 (ই) = 1 / লগ_ই (2) -> আমরা ফলাফল পেয়েছি
গাই এল


9

যেমনটি http://en.wikedia.org/wiki/Logarithm এ বলেছে :

logb(x) = logk(x) / logk(b)

যা এর মানে হল যে:

log2(x) = log10(x) / log10(2)

11
নোট করুন যে আপনি কর্মক্ষমতা বাড়াতে লগ 10 (2) কে সামঞ্জস্য করতে পারেন।
কর্সিকা

@ জোহানেস: আমি সন্দেহ করি যে সংকলকটি লগ 10 (2) এর প্রাক-গণনা করবে। সংকলক জানে না যে লগ 10 প্রতিটি সময় একই মান ফেরত দেবে। সমস্ত সংকলক জানে, লগ 10 (2) ধারাবাহিক কলগুলিতে বিভিন্ন মান ফেরত দিতে পারে।
আবেলেনকি

@ লেবেলঙ্কি: ঠিক আছে, আমি এটি ফিরিয়ে নিই। সংকলক যেহেতু log()বাস্তবায়নের উত্সটি কখনই দেখে না এটি এটি করবে না। আমার খারাপ।
জোয়

4
@ লেবেলঙ্কি: যেহেতু log10()সি স্ট্যান্ডার্ডে কোনও ফাংশন সংজ্ঞায়িত করা হয়েছে, তাই সংকলক ফলাফলটি পূর্বাভাস সহ "বিশেষত" চিকিত্সা করতে মুক্ত, যা আমি বিশ্বাস করি @ জোহানেসের পরামর্শ?
ক্যাফে

4
@ কার্লনোরম: আমি সবেমাত্র যাচাই করেছি এবং জিসিসি 4.7 কমপক্ষে log10(2)একটি ধ্রুবক দ্বারা প্রতিস্থাপন করেছি।
ক্যাফে

8

আপনি যদি এটি দ্রুত তৈরি করতে চান তবে আপনি বিট টুইডলিং হ্যাকের মতো লুকিং টেবিল ব্যবহার করতে পারেন (কেবলমাত্র পূর্ণসংখ্যার লগ 2)।

uint32_t v; // find the log base 2 of 32-bit v
int r;      // result goes here

static const int MultiplyDeBruijnBitPosition[32] = 
{
  0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
  8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};

v |= v >> 1; // first round down to one less than a power of 2 
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;

r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];

এ ছাড়া আপনার কম্পাইলারগুলির অন্তর্নির্মিত পদ্ধতিগুলি _BitScanReverseযা দেখতে পারে সেদিকে নজর দেওয়া উচিত দ্রুততর হবে, কারণ এটি সম্পূর্ণরূপে হার্ডওয়্যার নির্ণিত হতে পারে।

সম্ভাব্য সদৃশটি একবার দেখে নিন কীভাবে সি ++ এ পূর্ণসংখ্যা লগ 2 () করবেন?


কেন গুণ এবং টেবিল অনুসন্ধান শেষে? আপনি কেবল (v + 1) করতে পারবেন না যা দুটি পরবর্তী ক্ষমতার সাথে মিলিয়ে যাবে? এবং তারপরে, আপনি একের পর এক ডান পাশের
সাম্প্রতিক

@ সাফায়াতআহমেদ দয়া করে বর্ণনা করুন যে আপনি কীভাবে সেই পদ্ধতির সাথে কোনও সংখ্যার লগ 2 খুঁজে পেতে চান। আমি এই মানটি পাওয়ার সহজ উপায় জানি না। অনুসন্ধানের টেবিলের সাথে উপরের পাটিগণিত ব্যবহারের পাশাপাশি, গণনাটি করতে কেউ পুনরাবৃত্ত / পুনরাবৃত্ত আলগোরিদিম বা ডেডিকেটেড / বিল্টিন হার্ডওয়ার ব্যবহার করতে পারে।
বিকাউসবাক

বলুন 32 বিট ভেরিয়েবল ভি এর বিটগুলি এন (এমএসবি) এর মাধ্যমে 0 (এলএসবি) নম্বরযুক্ত রয়েছে। বলুন যে v এর সর্বাধিক উল্লেখযোগ্য সেট বিট n এটি কি সঠিক হবে যে এন ফ্লোর (লগ 2 (ভি)) উপস্থাপন করে? আপনি শুধু এন দেওয়া v খুঁজে পেতে আগ্রহী না?
সাফায়েত আহমেদ

আমি বুঝতে পেরেছিলাম যে আমি যা বর্ণনা করেছি তা আপনাকে কেবলমাত্র নিকটতম সর্বনিম্ন শক্তি 2 দেবে এবং আসল লগারিদমকে নয়। গুণ এবং সারণী সন্ধানের জন্য দুটি পাওয়ার থেকে লগারিদমে যাওয়ার জন্য। আপনি কিছু পরিমাণে 0x07C4ACDD নম্বরটি স্থানান্তর করছেন। আপনি যে পরিমাণ বামে স্থানান্তরিত করবেন তা দুটির শক্তির উপর নির্ভর করবে। সংখ্যাটি এমন, যে কোনও 5 টি বিটের ক্রমাগত ক্রমটি অনন্য। (0000 0111 1100 0100 0110 1100 1101 1101) আপনাকে ক্রম (00000) (00001) ... (11101) দেয়। আপনি কতটা স্থানান্তরিত হবে তার উপর নির্ভর করে আপনি এই 5-বিট নিদর্শনগুলির মধ্যে একটি পান। তারপরে সারণী অনুসন্ধান। খুব সুন্দর.
সাফায়েত আহমেদ


3
uint16_t log2(uint32_t n) {//but truncated
     if (n==0) throw ...
     uint16_t logValue = -1;
     while (n) {//
         logValue++;
         n >>= 1;
     }
     return logValue;
 }

মূলত টমলোগিকের মতোই ।


4
এই সমাধানটির সাথে বেশ কয়েকটি জিনিস ভুল আছে, তবে সাধারণভাবে আপনি যদি ভাসমান পয়েন্টগুলি এড়াতে চান তবে এটি দুর্দান্ত। আপনি এটি কাজ করার জন্য ওভারফ্লোতে নির্ভর করছেন যেহেতু আপনি -1 এর সাথে একটি স্বাক্ষরবিহীন পূর্ণসংখ্যার সূচনা করছেন। এটি 0 থেকে আরম্ভ করে এবং তারপরে 0 - কেস যা আপনি করেন তা পরীক্ষা করে ধরে ধরে ধরে মান - 1 প্রদান করে এটি ঠিক করা যেতে পারে। অন্য সমস্যাটি হ'ল এন == 0 এ যখন আপনি স্পষ্টভাবে উল্লেখ করবেন তখন আপনি লুপ থামার উপর নির্ভর করছেন। তা ছাড়া, যদি আপনি ভাসমান পয়েন্টগুলি এড়াতে চান তবে এটি দুর্দান্ত।
রিয়ান কুইন

2

আপনাকে গণিত এইচ (সি) বা সিমাথ (সি ++) অন্তর্ভুক্ত করতে হবে অবশ্যই মনে রাখবেন যে আমাদের জানা গণিতগুলি আপনাকে অনুসরণ করতে হবে ... কেবল সংখ্যা> 0।

উদাহরণ:

#include <iostream>
#include <cmath>
using namespace std;

int main(){
    cout<<log2(number);
}

2

আমার আরও স্পষ্টতা থাকা দরকার যে কেবলমাত্র উল্লেখযোগ্য বিটের অবস্থান এবং আমি যে মাইক্রোকন্ট্রোলারটি ব্যবহার করছিলাম তার কোনও গণিত গ্রন্থাগার ছিল না। আমি দেখতে পেয়েছি যে ইতিবাচক পূর্ণসংখ্যার মান আর্গুমেন্টের জন্য 2 ^ n মানের মধ্যে একটি লিনিয়ার সান্নিধ্য ব্যবহার করা ভালভাবে কাজ করে। কোডটি এখানে:

uint16_t approx_log_base_2_N_times_256(uint16_t n)
{
    uint16_t msb_only = 0x8000;
    uint16_t exp = 15;

    if (n == 0)
        return (-1);
    while ((n & msb_only) == 0) {
        msb_only >>= 1;
        exp--;
    }

    return (((uint16_t)((((uint32_t) (n ^ msb_only)) << 8) / msb_only)) | (exp << 8));
}

আমার মূল প্রোগ্রামে, আমাকে পূর্ণসংখ্যার ফলাফল সহ এন * লগ 2 (এন) / 2 গণনা করতে হবে:

টেম্প = (((uint32_t) এন) * প্রায়_লগ_বেস_2_ এন_টাইমস_256) / 512;

এবং সমস্ত 16 বিট মান 2% এর বেশি দ্বারা বন্ধ ছিল না


1

উপরের সমস্ত উত্তর সঠিক। নীচের আমার এই উত্তর কারওর প্রয়োজন হলে সহায়ক হতে পারে। আমরা অনেকগুলি প্রশ্নে এই প্রয়োজনীয়তাটি দেখেছি যা আমরা সি ব্যবহার করে সমাধান করছি

log2 (x) = logy (x) / logy (2)

তবে, আপনি যদি সি ভাষা ব্যবহার করছেন এবং আপনি পূর্ণসংখ্যার ফলাফল চান, আপনি নিম্নলিখিত ব্যবহার করতে পারেন:

int result = (int)(floor(log(x) / log(2))) + 1;

আশাকরি এটা সাহায্য করবে.


0

আপনার গণিতের বেসিক কোর্সের সাথে পরামর্শ করুন log n / log 2,। আপনি চয়ন করেন logবা এক্ষেত্রে নতুন বেসের সাথে log10ভাগ করে নেওয়া logকৌশলটি কার্যকর করে তা বিবেচ্য নয়।


0

উস্তামান সংগত যা করেছিলেন তার উন্নত সংস্করণ

static inline uint64_t
log2(uint64_t n)
{
    uint64_t val;
    for (val = 0; n > 1; val++, n >>= 1);

    return val;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.