c++ - আমি যদি স্বাক্ষরবিহীন পূর্ণসংখ্যার নিকটতম ছোট বা সমান সমান পূর্ণসংখ্যার সাথে গোল করতে চাই, তবে আমি কি 2 দ্বারা ভাগ করে 2 দিয়ে গুণ করতে পারি?




(5)

উদাহরণ স্বরূপ :

f(8)=8
f(9)=8

আমি কি x = x/2*2; ? কোনও ঝুঁকি আছে যে সংকলকটি এই জাতীয় অভিব্যক্তিটি অপ্টিমাইজ করবে?


আপনার মানগুলি যদি আপনি যেভাবে স্বাক্ষরিত কোনও প্রকারের হয় তবে সবচেয়ে সহজ

x & -2;

স্বাক্ষরবিহীন পাটিগণিতের বিস্ময়গুলি এটিকে তৈরি করে যে -2 x এর x রূপান্তরিত হয় এবং এর বিট প্যাটার্ন থাকে যা সমস্ত থাকে তবে সর্বনিম্ন উল্লেখযোগ্য বিটের জন্য যা 0

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

অতিরিক্ত বোনাস, সুপারক্যাট হিসাবে চিহ্নিত হিসাবে, এটি কেবল স্বাক্ষরযুক্ত প্রকারকে স্বাক্ষরবিহীন প্রকারে রূপান্তর ব্যবহার করে। এটি মডুলো পাটিগণিত হিসাবে মান দ্বারা ভাল সংজ্ঞায়িত করা হয়। সুতরাং ফলাফলটি সর্বদা UTYPE_MAX-1 UTYPE এর স্বাক্ষরযুক্ত প্রকারের x । বিশেষত, এটি স্বাক্ষরিত ধরণের জন্য প্ল্যাটফর্মের সাইন প্রতিনিধিত্বের থেকে পৃথক।


আপনি x / 2 * 2 লিখতে পারেন এবং সংকলক খুব স্বল্প দক্ষ কোড তৈরি করবে যদি x এর স্বাক্ষরযুক্ত টাইপ থাকে তবে কমপক্ষে উল্লেখযোগ্য বিট সাফ করতে।

বিপরীতে, আপনি লিখতে পারেন:

x = x & ~1;

বা সম্ভবত কম পাঠযোগ্য:

x = x & -2;

অথবা এমনকি

x = (x >> 1) << 1;

অথবা এটিও:

x = x - (x & 1);

বা সুপারক্যাট দ্বারা প্রস্তাবিত এই শেষটি, যা সমস্ত পূর্ণসংখ্যার ধরণ এবং উপস্থাপনার ধনাত্মক মানগুলির জন্য কাজ করে:

x = (x | 1) ^ 1;

উপরোক্ত সমস্ত প্রস্তাবনা 2 এর পরিপূরক আর্কিটেকচারে সমস্ত স্বাক্ষরযুক্ত পূর্ণসংখ্যার ধরণের জন্য সঠিকভাবে কাজ করে। সংকলকটি সর্বোত্তম কোড তৈরি করবে কিনা তা কনফিগারেশন এবং বাস্তবায়নের মানের প্রশ্ন।

তবে নোট করুন যে x & (~1u) যদি unsigned int x & (~1u) চেয়ে বড় হয় তবে x & (~1u) কাজ করে না। এটি একটি পাল্টা স্বজ্ঞাত ফলস্বরূপ। আপনি যদি স্বাক্ষরবিহীন ধ্রুবকটি ব্যবহার করার জন্য জিদ করেন, আপনাকে অবশ্যই x & ~(uintmax_t)1 x & ~1ULL হবে এমনকি x & ~1ULL ব্যর্থ হবে যদি x unsigned long long x & ~1ULL চেয়ে বড় ধরণের থাকে। বিষয়টিকে আরও খারাপ করার জন্য, অনেক প্ল্যাটফর্মে এখন uintmax_t চেয়ে বড় uintmax_t যেমন __uint128_t

এখানে একটি সামান্য মানদণ্ড দেওয়া হল:

typedef unsigned int T;

T test1(T x) {
    return x / 2 * 2;
}

T test2(T x) {
    return x & ~1;
}

T test3(T x) {
    return x & -2;
}

T test4(T x) {
    return (x >> 1) << 1;
}

T test5(T x) {
    return x - (x & 1);
}

T test6(T x) {  // suggested by supercat
    return (x | 1) ^ 1;
}

T test7(T x) {  // suggested by Mehrdad
    return ~(~x | 1);
}

T test1u(T x) {
    return x & ~1u;
}

রুসলানের পরামর্শ অনুসারে, গডবোল্টের সংকলক এক্সপ্লোরার পরীক্ষা করে দেখা যায় যে উপরের সমস্ত বিকল্পের জন্য gcc -O1 unsigned int জন্য একই সঠিক কোড তৈরি করে, তবে T টাইপ T unsigned long long শোতে test1u জন্য পৃথক কোড প্রদর্শন করে।


কেবল নিম্নলিখিত ব্যবহার করুন:

template<class T>
inline T f(T v)
{
    return v & (~static_cast<T>(1));
}

এটি যে ফাংশন তা ভয় করবেন না, সংকলকটি অবশেষে এটি যথাযথ 1 এর সাথে ঠিক v & (~ 1) এ অনুকূলিত করতে হবে।


যেহেতু আপনি নির্দিষ্ট করেছেন পূর্ণসংখ্যা স্বাক্ষরবিহীন, তাই আপনি এটি একটি সাধারণ মুখোশ দিয়ে করতে পারেন:

x & (~1u)

যা এলএসবিকে শূন্যে সেট করবে, এভাবে তাত্ক্ষণিক সমান সংখ্যা তৈরি করবে যা x চেয়ে বড় নয়। এটি হ'ল, যদি x এর একটি টাইপ থাকে যা unsigned int চেয়ে বৃহত্তর হয় না।

আপনি অবশ্যই 1 বৃহত্তর x হিসাবে একই ধরণের হতে বাধ্য করতে পারেন:

x & ~((x & 1u) | 1u)

তবে এই মুহুর্তে, আপনার অবশ্যই অবলম্বন করার অনুশীলন হিসাবে এই পদ্ধতির দিকে নজর দেওয়া উচিত, এবং বাথশেবার উত্তর গ্রহণ করা উচিত।

আমি অবশ্যই স্ট্যান্ডার্ড লাইব্রেরিটি ভুলে গিয়েছিলাম। আপনি যদি stdint.h অন্তর্ভুক্ত stdint.h (বা cstdint , আপনার যেমন সি ++ কোড থাকা উচিত)। আপনি বাস্তবায়নের বিশদটি যত্ন নিতে দিতে পারেন:

uintmax_t const lsb = 1;
x & ~lsb;

অথবা

x & ~UINTMAX_C(1)

সি এবং সি ++ অপ্টিমাইজেশনে সাধারণত "যেন" বিধিটি ব্যবহার করে। গণনার ফলাফল অবশ্যই এমন হতে হবে যেন কম্পাইলারটি আপনার কোডটি অনুকূলিত করে নি।

এই ক্ষেত্রে, 9/2*2=8 । সংকলক ৮. ফলাফল অর্জনের জন্য যে কোনও পদ্ধতি ব্যবহার করতে পারে This এতে বিটমাস্ক, বিট শিফট বা একই সিপিইউ-নির্দিষ্ট হ্যাক অন্তর্ভুক্ত রয়েছে যা একই ফলাফল দেয় (x86 বেশ কয়েকটি কৌশল রয়েছে যা নির্ভর করে যে এটি পয়েন্টারের মধ্যে পার্থক্য রাখে না on এবং পূর্ণসংখ্যা, সি এবং সি ++ এর বিপরীতে)।





c