(একটি & # xFF) এর চেয়ে (% 256) আলাদা কেন?


145

আমি সর্বদা ধরে নিয়েছিলাম যে (a % 256)অপটিমাইজারটি করার সময় স্বাভাবিকভাবেই একটি দক্ষ বিটওয়াইজ অপারেশন ব্যবহার করা হবে, যেন আমি লিখেছি (a & 0xFF)

সংকলক এক্সপ্লোরার gcc-6.2 (-O3) এ পরীক্ষা করার সময়:

// Type your code here, or load an example.
int mod(int num) {
    return num % 256;
}

mod(int):
    mov     edx, edi
    sar     edx, 31
    shr     edx, 24
    lea     eax, [rdi+rdx]
    movzx   eax, al
    sub     eax, edx
    ret

এবং অন্যান্য কোড চেষ্টা করার সময়:

// Type your code here, or load an example.
int mod(int num) {
    return num & 0xFF;
}

mod(int):
    movzx   eax, dil
    ret

দেখে মনে হচ্ছে আমি পুরোপুরি কিছু মিস করছি। কোন ধারনা?


64
0xFF 255 256. নয়
ঋষিকেশ রাজে

186
@ Ishষিকেশরাজ: তাই? %হয় না &
usr2564301

27
@ Ishষিকেশরাজ: আমি নিশ্চিত যে ওপি খুব সচেতন। এগুলি বিভিন্ন ক্রিয়াকলাপের সাথে ব্যবহৃত হচ্ছে।
চিয়ার্স এবং এইচটিএইচ - আল্ফ

28
সুদ আউট, আপনি ভাল ফলাফল পেতে পারি যদি numহয় unsigned?
বৎশেবা

20
@ Ikষিকেশরাজ রাজি বিটওয়াইজ এবং 0xFF স্বাক্ষরবিহীন পূর্ণসংখ্যার জন্য মডুলো 2 ^ 8 এর সমতুল্য।
2501

উত্তর:


230

এটি একই না. চেষ্টা করুন num = -79, এবং আপনি উভয় ক্রিয়াকলাপ থেকে পৃথক ফলাফল পাবেন। (-79) % 256 = -79, যদিও (-79) & 0xffকিছু ইতিবাচক সংখ্যা।

ব্যবহার করে unsigned int, অপারেশনগুলি একই এবং কোডটি সম্ভবত একই হবে।

পিএস- কেউ মন্তব্য করেছেন

তারা একই হতে হবে না, a % bহিসাবে সংজ্ঞায়িত করা হয় a - b * floor (a / b)

এটি সি, সি ++, অবজেক্টিভ-সি (যেমন সমস্ত ভাষা যেখানে প্রশ্নের কোডটি সংকলন করবে) তে সংজ্ঞায়িত হয় না।


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
মার্টিজন পিটারস

53

সংক্ষিপ্ত উত্তর

-1 % 256ফলন -1এবং 255যা হয় না -1 & 0xFF। অতএব, অপটিমাইজেশনটি ভুল হবে।

দীর্ঘ উত্তর

সি ++ এর কনভেনশন রয়েছে (a/b)*b + a%b == aযা বেশ স্বাভাবিক বলে মনে হয়। a/bসর্বদা ভগ্নাংশের অংশ (0 এর দিকে ছাঁটাই করা) ছাড়াই গাণিতিক ফলাফল প্রদান করে। ফলস্বরূপ, 0 এর a%bমতো aবা একই চিহ্ন রয়েছে ।

বিভাগ -1/256উৎপাদনের 0তাই -1%256হওয়া আবশ্যক -1অর্ডার উপরে শর্ত সন্তুষ্ট করার জন্য ( (-1%256)*256 + -1%256 == -1)। এটি -1&0xFFযা থেকে স্পষ্টতই আলাদা 0xFF। অতএব, সংকলকটি আপনার পছন্দ মতো অনুকূলিতকরণ করতে পারে না।

প্রাসঙ্গিক অধ্যায় C ++ স্ট্যান্ডার্ডের [expr.mul §4] N4606 হিসাবে পদ বলে:

অবিচ্ছেদ্য অপারেন্ডগুলির জন্য /অপারেটর বাতিল হওয়া কোনও ভগ্নাংশের সাথে বীজগণিতের ভাগফল উপার্জন করে ; ভাগফল যদি a/bফলাফলের ধরণে উপস্থাপনযোগ্য হয় তবে [...] এর (a/b)*b + a%bসমান a

অপ্টিমাইজেশন সক্ষম করা

তবে, প্রকারগুলি ব্যবহার করে unsigned, উপরোক্ত সম্মেলনটি সন্তুষ্ট করে অনুকূলকরণটি সম্পূর্ণ সঠিক হবে :

unsigned(-1)%256 == 0xFF

আরও দেখুন এই

অন্যান্য ভাষাসমূহ

আপনি উইকিপিডিয়ায় সন্ধান করতে পারেন এটি বিভিন্ন প্রোগ্রামিং ভাষায় খুব আলাদাভাবে পরিচালনা করা হয় ।


50

যেহেতু সি ++ 11, negative num % 256ণাত্মক হলে numতা ইতিবাচক হতে হবে ।

সুতরাং বিট প্যাটার্নটি আপনার সিস্টেমে স্বাক্ষরিত ধরণের প্রয়োগের উপর নির্ভর করবে: নেতিবাচক প্রথম যুক্তির জন্য, ফলাফলটি সর্বনিম্ন উল্লেখযোগ্য 8 বিটের নিষ্কাশন নয়।

numআপনার ক্ষেত্রে থাকলে এটি অন্যরকম হবে unsigned: এই দিনগুলিতে আপনি যে অপটিমাইজেশনটি উদ্ধৃত করেছেন তার প্রায়শই আমি একটি সংকলক আশা করছিলাম ।


6
প্রায় কিন্তু বেশ না। যদি numnegativeণাত্মক হয় তবে num % 256শূন্য বা নেতিবাচক (ওরফে অ-ধনাত্মক)।
নায়ুকি

5
কোন আইএমও, মানক হিসাবে ভুল: গাণিতিকভাবে মডুলো অপারেশনটি এই ক্ষেত্রে 256 বিভাজকের স্বাক্ষর নিতে হবে। কেন তা বিবেচনা করবেন তা বোঝার জন্য (-250+256)%256==6, তবে (-250%256)+(256%256)মানদণ্ড অনুসারে অবশ্যই "অ-ধনাত্মক" হওয়া উচিত এবং তাই নয় 6। এর মতো ভাঙ্গা সাহসিকতার বাস্তব জীবনের পার্শ্ব প্রতিক্রিয়া রয়েছে: উদাহরণস্বরূপ, সংখ্যার সমন্বয়গুলিতে "জুম আউট" রেন্ডারিংয়ের সময় সমস্ত স্থানাঙ্ককে অ-নেতিবাচক রাখার জন্য চিত্রটি স্থানান্তর করতে হয়।
মাইকেল 17 ই

2
আপনি চিঠির গণিত সংজ্ঞা মেনে চললেও @ মিশেল মডুলাস কখনও কখনও অতিরিক্ত বিতরণ করা হয়নি ("সম্পত্তি হিসাবে এই সম্পত্তিটির ভুল নাম!)। উদাহরণস্বরূপ, (128+128)%256==0কিন্তু (128%256)+(128%256)==256। সম্ভবত নির্দিষ্ট আচরণ সম্পর্কে ভাল আপত্তি আছে, তবে এটি যে আপনি বলেছেন সেটাই আমার কাছে পরিষ্কার নয় clear
ড্যানিয়েল ওয়াগনার

1
@ ড্যানিয়েল ওয়াগনার, আপনি ঠিক বলেছেন, অবশ্যই আমি "এসোসিয়েটিভ" এর সাথে ভুল মন্তব্য করি। তবে, যদি কেউ বিভাজনের চিহ্ন রাখে এবং মডিউলার গাণিতিকগুলিতে সমস্ত কিছু গণনা করে, বিতরণকারী সম্পত্তি হোল্ড করে; আপনার উদাহরণে আপনি হবে 256==0। মূলটি হল Nমডুলো Nগাণিতিকের ঠিক সম্ভাব্য মান থাকা , যা কেবলমাত্র তখনই সম্ভব যখন সমস্ত ফলাফলের পরিসীমা থাকে 0,...,(N-1), না -(N-1),...,(N-1)
মাইকেল 18

6
@Michael: ছাড়া% একটি ফরম অপারেটরের নয়, এটা একটি ব্যাপার বাকি অপারেটর।
জোরেেন

11

সংকলকের যুক্তিতে আমার টেলিপ্যাথিক অন্তর্দৃষ্টি নেই, তবে ক্ষেত্রে %নেতিবাচক মানগুলি (এবং শূন্যের দিকে বিভাজনগুলি) নিয়ে কাজ করার প্রয়োজনীয়তা রয়েছে, তবে &ফলাফলটি সর্বদা কম 8 বিট থাকে।

sar"গাণিতিক অধিকার শিফট", সাইন বিট মান খোলসা বিট পূরণ মত আমাকে নির্দেশ ধ্বনি।


0

গাণিতিকভাবে বলতে গেলে, মডুলো নিম্নলিখিত হিসাবে সংজ্ঞায়িত করা হয়েছে:

a% b = a - b * মেঝে (a / b)

এই অধিকার এখানে আপনার জন্য এটি পরিষ্কার করা উচিত। আমরা পূর্ণসংখ্যার জন্য মেঝে নির্মূল করতে পারি কারণ পূর্ণসংখ্যা বিভাগ মেঝে (a / b) এর সমান। তবে, কম্পাইলারটি যদি আপনার পরামর্শ মতো একটি সাধারণ কৌশল ব্যবহার করে থাকে তবে এটি সমস্ত এবং সমস্ত খ এর জন্য কাজ করা দরকার। দুর্ভাগ্যক্রমে, এটি ঠিক এটি নয়। গাণিতিকভাবে বলতে গেলে, আপনার কৌশলটি স্বাক্ষরবিহীন পূর্ণসংখ্যার জন্য 100% সঠিক (আমি একটি উত্তরের সাথে স্বাক্ষরিত পূর্ণসংখ্যার বিরতি দেখতে পাচ্ছি তবে আমি এটি নিশ্চিত করতে বা অস্বীকার করতে পারি - a% b ইতিবাচক হওয়া উচিত)। যাইহোক, আপনি এই কৌশলটি সমস্ত বি জন্য করতে পারেন? সম্ভবত না. এজন্য সংকলক এটি করে না। সর্বোপরি, যদি মডুলো সহজেই একটি বিটওয়াইজ অপারেশন হিসাবে লিখিত হয়, তবে আমরা কেবল সংযোজন এবং অন্যান্য ক্রিয়াকলাপগুলির মতো একটি মডুলো সার্কিট যুক্ত করব।


4
আমি মনে করি আপনি "ছাঁটাই" দিয়ে "তল" কে বিভ্রান্ত করছেন। প্রারম্ভিক কম্পিউটারগুলি কাটাকাটি বিভাগ ব্যবহার করত কারণ জিনিসগুলি সমানভাবে বিভক্ত হওয়ার ক্ষেত্রে এমনকি তলিত বিভাগের চেয়ে গণনা করা প্রায়শই সহজ। আমি খুব কম কয়েকটি ক্ষেত্রে দেখেছি যেখানে কাটা বিভাগগুলি মেঝে বিভাগের চেয়ে বেশি কার্যকর ছিল তবে অনেকগুলি ভাষা কাটা বিভাগ ব্যবহারের ক্ষেত্রে ফোরট্রানের নেতৃত্ব অনুসরণ করে।
সুপারক্যাট

@supercat গাণিতিকভাবে ভাষী, তল হয় আরোপ করা। তাদের উভয়ের একই প্রভাব রয়েছে। এগুলি কম্পিউটারে একই প্রয়োগ করা নাও হতে পারে তবে তারা একই কাজ করে।
ব্যবহারকারী 64742

5
@ দ্য গ্রেটডাক: নেতিবাচক সংখ্যার জন্য এগুলি এক নয়। মেঝেটি -2.3হ'ল -3, আপনি যদি -2.3কোনও পূর্ণসংখ্যার সাথে কাটা করেন -2En.wikedia.org/wiki/Truncation দেখুন । "নেতিবাচক সংখ্যার জন্য কাটা মেঝে ফাংশন হিসাবে একই দিক দিয়ে গোল হয় না"। এবং %নেতিবাচক সংখ্যার জন্য আচরণ হ'ল কারণ হ'ল ওপি বর্ণিত আচরণটি দেখছে।
মার্ক ডিকিনসন

@ মার্কডিকিনসন আমি নিশ্চিত যে সি ++ তে থাকা মডুলো ইতিবাচক বিভাজনকারীদের জন্য ইতিবাচক মান দেয় তবে আমি তর্ক করব না।
ব্যবহারকারী 64742

1
@ দ্য গ্রেটডাক - উদাহরণটি দেখুন: cpp.sh/3g7h (নোট করুন যে C ++ 98 দুটি সম্ভাব্য রূপগুলির মধ্যে কোনটি ব্যবহৃত হয়েছিল তা নির্ধারণ করেনি, তবে এটি আরও সাম্প্রতিক মানগুলি করে, সুতরাং এটি সম্ভব যে আপনি সি ++ এর একটি বাস্তবায়ন ব্যবহার করেছেন) অতীতে যা এটি
অন্যভাবে করেছিল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.