সি # তে বিটমাস্ক ব্যবহার করা হচ্ছে


100

ধরা যাক আমার নিম্নলিখিত আছে

int susan = 2; //0010
int bob = 4; //0100
int karen = 8; //1000

এবং আমি একটি পদ্ধতির পরামিতি হিসাবে 10 (8 + 2) পাস করেছি এবং আমি এটি সুসান এবং ক্যারেন বোঝাতে ডিকোড করতে চাই

আমি জানি যে 10 1010

তবে একটি নির্দিষ্ট বিট হিসাবে চেক করা হয়েছে কিনা তা দেখার জন্য আমি কীভাবে কিছু যুক্তি করতে পারি

if (condition_for_karen) // How to quickly check whether effective karen bit is 1

এই মুহুর্তে আমি যা ভাবতে পারি তা হ'ল আমি পাস করা নম্বরটি কিনা তা যাচাই করা

14 // 1110
12 // 1100
10 // 1010
8 //  1000

আমার বাস্তব বিশ্বের দৃশ্যে যখন আমার কাছে আরও বড় সংখ্যক আসল বিট রয়েছে, তখন এটি অযৌক্তিক বলে মনে হয়, কেবল ক্যারেনের শর্তটি পূরণ করছি কি না তা খতিয়ে দেখার জন্য একটি মাস্ক ব্যবহার করা এর চেয়ে ভাল উপায় কী?

আমি বাম দিকে সরে যাওয়ার কথা ভাবতে পারি তারপরে পিছনে আবার ডান স্থানান্তরিত করতে চাইলে আবার বিট সাফ করতে চাইলে আমি আগ্রহী, তবে এটিও জটিল বলে মনে হচ্ছে।


7
শুধু ব্যবহার সম্পর্কে মন্তব্য করতে হবে। আপনি যদি বিট অপারেশন করে থাকেন তবে আপনার কেবল বিট ম্যানিপুলেটিং অপারেটর ব্যবহার করা উচিত। অর্থাত, এটিকে (8 | 2) হিসাবে ভাবেন, (8 + 2) নয়।
জেফ মার্কাডো

4
কারেন ততক্ষনে আপনার ম্যানেজারের সাথে কথা বলতে চাই।
ক্রিথিক

উত্তর:


201

এটি করার Theতিহ্যগত উপায় হ'ল Flagsএকটিতে বৈশিষ্ট্যটি ব্যবহার করা enum:

[Flags]
public enum Names
{
    None = 0,
    Susan = 1,
    Bob = 2,
    Karen = 4
}

তারপরে আপনি নিম্নলিখিত হিসাবে একটি নির্দিষ্ট নামের জন্য পরীক্ষা করতে চাই:

Names names = Names.Susan | Names.Bob;

// evaluates to true
bool susanIsIncluded = (names & Names.Susan) != Names.None;

// evaluates to false
bool karenIsIncluded = (names & Names.Karen) != Names.None;

লজিকাল বিটওয়াইস সংমিশ্রণগুলি মনে রাখা শক্ত হতে পারে, তাই আমি একটি FlagsHelperশ্রেণীর সাহায্যে নিজের জীবনকে সহজ করে তুলি *:

// The casts to object in the below code are an unfortunate necessity due to
// C#'s restriction against a where T : Enum constraint. (There are ways around
// this, but they're outside the scope of this simple illustration.)
public static class FlagsHelper
{
    public static bool IsSet<T>(T flags, T flag) where T : struct
    {
        int flagsValue = (int)(object)flags;
        int flagValue = (int)(object)flag;

        return (flagsValue & flagValue) != 0;
    }

    public static void Set<T>(ref T flags, T flag) where T : struct
    {
        int flagsValue = (int)(object)flags;
        int flagValue = (int)(object)flag;

        flags = (T)(object)(flagsValue | flagValue);
    }

    public static void Unset<T>(ref T flags, T flag) where T : struct
    {
        int flagsValue = (int)(object)flags;
        int flagValue = (int)(object)flag;

        flags = (T)(object)(flagsValue & (~flagValue));
    }
}

এটি আমাকে উপরের কোডটি আবার লিখতে অনুমতি দেবে:

Names names = Names.Susan | Names.Bob;

bool susanIsIncluded = FlagsHelper.IsSet(names, Names.Susan);

bool karenIsIncluded = FlagsHelper.IsSet(names, Names.Karen);

দ্রষ্টব্য আমি Karenএটি করে সেটে যোগ করতে পারি:

FlagsHelper.Set(ref names, Names.Karen);

এবং আমি Susanএকইভাবে মুছে ফেলতে পারি :

FlagsHelper.Unset(ref names, Names.Susan);

* পোরজেস যেমন উল্লেখ করেছে, IsSetউপরের পদ্ধতির একটি সমতুল্য ইতিমধ্যে Enum.HasFlag। নেট 4.0: এ বিদ্যমান । Setএবং Unsetপদ্ধতি, যদিও সমতুল আছে প্রদর্শিত না; সুতরাং আমি এখনও বলতে পারি এই শ্রেণীর কিছু যোগ্যতা রয়েছে।


দ্রষ্টব্য: এনামগুলি ব্যবহার করা এই সমস্যাটি মোকাবেলার কেবল প্রচলিত উপায়। পরিবর্তে ইনটগুলি ব্যবহার করার জন্য আপনি উপরের সমস্ত কোডটি সম্পূর্ণরূপে অনুবাদ করতে পারেন এবং এটি ঠিক তেমন কাজ করবে।


14
আসলে কাজ করার জন্য প্রথম কোড হওয়ার জন্য +1। আপনি এটিও করতে পারেন (names & Names.Susan) == Names.Susan, যার কোনও প্রয়োজন হয় না None
ম্যাথু ফ্ল্যাশেন

4
@ ম্যাথু: ওহ হ্যাঁ, ভাল কথা। আমি অনুমান করি যে আমি সবসময় Noneআমার সমস্ত এনামগুলির জন্য একটি মূল্য সংজ্ঞায়িত করার অভ্যাসে পেয়েছি, কারণ আমি দেখতে পেয়েছি এটি অনেক পরিস্থিতিতেই সুবিধাজনক হয়ে ওঠে।
ড্যান তাও

33
এটি অন্তর্নির্মিত, আপনার var susanIsIncluded = names.HasFlag(Names.Susan);
সহায়তার

4
@ পোর্জস: বাহ, আমি কীভাবে মিস করেছি তা জানিনা ... এটি উল্লেখ করার জন্য ধন্যবাদ! (দেখে মনে হচ্ছে এটি কেবল নেট নেট 4.0.০ হিসাবে উপলব্ধ, যদিও ... এছাড়াও, Setপদ্ধতির কোনও সমতুল্য নেই no সুতরাং, আমি বলব সহায়ক সহায়কগুলি কমপক্ষে সম্পূর্ণ নিরর্থক নয় ))
ড্যান তাও

6
দ্রষ্টব্য, যে ব্যবহারের names.HasFlag(Names.Susan)মত (names & Names.Susan) == Names.Susanযা সর্বদা পছন্দ হয় না (names & Names.Susan) != Names.None। উদাহরণস্বরূপ, আপনি যদি পরীক্ষা করেন names.HasFlag(Names.none)বাnames.HasFlag(Names.Susan|Names.Karen)
এবিসিড

20
if ( ( param & karen ) == karen )
{
  // Do stuff
}

বিটওয়াইস 'এবং' ক্যারেনকে "উপস্থাপন করে" বিট ব্যতীত সমস্ত কিছু মুখোশ দেয়। যতক্ষণ না প্রতিটি ব্যক্তিকে একক বিট পজিশনে প্রতিনিধিত্ব করা হয়, আপনি একাধিক লোককে সরল করে পরীক্ষা করতে পারেন:

if ( ( param & karen ) == karen )
{
  // Do Karen's stuff
}
if ( ( param & bob ) == bob )
  // Do Bob's stuff
}

12

আমি এখানে একটি উদাহরণ অন্তর্ভুক্ত করেছি যা দেখায় যে কীভাবে আপনি কোনও উপাত্ত হিসাবে একটি ডেটাবেস কলামে মুখোশটি সংরক্ষণ করতে পারেন এবং আপনি কীভাবে পরে মুখোশটি পুনঃস্থাপন করবেন:

public enum DaysBitMask { Mon=0, Tues=1, Wed=2, Thu = 4, Fri = 8, Sat = 16, Sun = 32 }


DaysBitMask mask = DaysBitMask.Sat | DaysBitMask.Thu;
bool test;
if ((mask & DaysBitMask.Sat) == DaysBitMask.Sat)
    test = true;
if ((mask & DaysBitMask.Thu) == DaysBitMask.Thu)
    test = true;
if ((mask & DaysBitMask.Wed) != DaysBitMask.Wed)
    test = true;

// Store the value
int storedVal = (int)mask;

// Reinstate the mask and re-test
DaysBitMask reHydratedMask = (DaysBitMask)storedVal;

if ((reHydratedMask & DaysBitMask.Sat) == DaysBitMask.Sat)
    test = true;
if ((reHydratedMask & DaysBitMask.Thu) == DaysBitMask.Thu)
    test = true;
if ((reHydratedMask & DaysBitMask.Wed) != DaysBitMask.Wed)
    test = true;

আমি অনুরূপ কিছু করেছি তবে মুখোশটি সংজ্ঞায়িত করার সময় আমি সোম = ম্যাথ.পাওয়ার (2, 0), মঙ্গলগুলি = ম্যাথ.প্যাও (2, 1), বুধ = ম্যাথ.পা (2, 2), ইত্যাদি করেছি তাই বিট পজিশন ডেসিমাল রূপান্তর হিসাবে বাইনারি ব্যবহৃত হয় না এমন যারা ব্যবহার করেন তাদের ক্ষেত্রে এটি আরও স্পষ্ট। ব্লাইন্ডির কাজটি খুব ভাল, কারণ এটি মুখোশ বিট স্থানান্তরিত করে বুলিয়ান ফলাফলে পরিণত হয়।
এনালগ আর্সননিস্ট

10

সহজ পথ:

[Flags]
public enum MyFlags {
    None = 0,
    Susan = 1,
    Alice = 2,
    Bob = 4,
    Eve = 8
}

পতাকাগুলি সেট করতে লজিকাল "বা" অপারেটর ব্যবহার করুন |:

MyFlags f = new MyFlags();
f = MyFlags.Alice | MyFlags.Bob;

এবং কোনও পতাকা অন্তর্ভুক্ত রয়েছে কিনা তা পরীক্ষা করতে HasFlag:

if(f.HasFlag(MyFlags.Alice)) { /* true */}
if(f.HasFlag(MyFlags.Eve)) { /* false */}

এই সমস্ত তথ্য ইতিমধ্যে উপরে সরবরাহ করা হয়েছে বলে মনে হচ্ছে। আপনি যদি কোনও নতুন তথ্য দিচ্ছেন তবে আপনার এটি স্পষ্টভাবে চিহ্নিত করা উচিত।
Sonyisda1

4
ব্যবহারের সহজ উদাহরণ HasFlag()এবং [Flags]অন্যান্য উত্তর প্রদান করা হয়নি।
এ-শারাবিয়ানি

7

বিটমাস্কগুলি একত্রিত করতে আপনি বিটওয়াইস- বা ব্যবহার করতে চান । তুচ্ছ ক্ষেত্রে যেখানে আপনি একত্রিত প্রতিটি মানের ঠিক 1 বিট থাকে (আপনার উদাহরণের মতো), এটি যুক্ত করার সমতুল্য। আপনার যদি তবে বিটগুলি ওভারল্যাপিং করে থাকে, বা 'ইনগিংয়ের' ক্ষেত্রে কেসটি হ্যান্ডল করে।

বিটমাস্কটি ডিকোড করার জন্য আপনাকে এবং আপনার মানকে একটি মাস্ক দিয়ে যেমন:

if(val & (1<<1)) SusanIsOn();
if(val & (1<<2)) BobIsOn();
if(val & (1<<3)) KarenIsOn();

4
আপনি সি # তে বুলিয়ান হিসাবে কোনও পূর্ণসংখ্যা ব্যবহার করতে পারবেন না।
শেডো

0

বিটমাস্ক বনাম স্বতন্ত্র বুলগুলি ব্যবহার করার অন্য একটি সত্যিকারের কারণ হ'ল ওয়েব বিকাশকারী হিসাবে, কোনও ওয়েবসাইটকে অন্য ওয়েবসাইটের সাথে সংহত করার সময়, আমাদের প্রায়শই ক্যোরিস্ট্রিংয়ে প্যারামিটার বা পতাকা প্রেরণ করা প্রয়োজন। যতক্ষণ না আপনার সমস্ত পতাকা বাইনারি হয় ততক্ষণ এটি বিলের মতো একাধিক মান প্রেরণের চেয়ে বিটমাস্ক হিসাবে একটি মানকে ব্যবহার করা আরও সহজ করে তোলে। আমি জানি যে ডেটা প্রেরণের জন্য আরও কিছু উপায় রয়েছে (জিইটি, পোষ্ট, ইত্যাদি), তবে ক্যোরিস্ট্রিংয়ের একটি সাধারণ প্যারামিটারটি সংবেদনশীল আইটেমগুলির জন্য বেশিরভাগ সময়ই যথেষ্ট। একটি বাহ্যিক সাইটের সাথে যোগাযোগের জন্য কোয়েরিস্ট্রিংয়ে 128 টি বুলি মান প্রেরণের চেষ্টা করুন। এটি ব্রাউজারগুলিতে ইউআরএল ক্যোরিস্ট্রিংগুলিতে সীমাবদ্ধতা না চাপানোর অতিরিক্ত ক্ষমতাও দেয়


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