জাভার মডুলাসের মতো নেতিবাচক সংখ্যার সাথে আচরণ করার সর্বোত্তম উপায়?


103

জাভাতে যখন আপনি করবেন

a % b

যদি কোনওটি নেতিবাচক হয় তবে এটি খ এর মতো মোড়কের পরিবর্তে নেতিবাচক ফলাফল দেয়। এটি ঠিক করার সর্বোত্তম উপায় কী? আমি ভাবতে পারি একমাত্র উপায়

a < 0 ? b + a : a % b

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

4
এটা আমার জন্য খুব অদ্ভুত। আমি ভেবেছি এটি কেবল নেতিবাচক ফিরে আসবে যদি বি নেতিবাচক হয়।
বেড়ান ent


2
এইটা. তবে এই প্রশ্নের শিরোনামটির নাম পরিবর্তন করা উচিত। আমি যদি এই প্রশ্নের জন্য অনুসন্ধান করতাম তবে আমি সেই প্রশ্নটিতে ক্লিক করব না কারণ জাভা মডুলাস কীভাবে কাজ করে তা আমি ইতিমধ্যে জানি।
fent

4
আমি এটিকে "কেন -13% 64 = 51?" থেকে এটির নামকরণ করেছি, যা মিলিয়ন বছরে কখনও কারও অনুসন্ধান করা হবে না। সুতরাং এই প্রশ্নের শিরোনামটি আরও ভাল, এবং মডুলাস, নেতিবাচক, গণনা, সংখ্যাগুলির মতো কীওয়ার্ডগুলিতে অনেক বেশি অনুসন্ধানযোগ্য।
এরিক রবার্টসন

উত্তর:


144

এটি% b = a - a / b * b এর মতো আচরণ করে; অর্থাৎ এটি বাকি

আপনি (একটি% বি + বি)% বি করতে পারেন


এই অভিব্যক্তিটি ইতিবাচক বা নেতিবাচক হোক না কেন ফলাফলের (a % b)চেয়ে অগত্যা কম হওয়ায় কাজ করে । যোগ করা নেতিবাচক মানগুলির যত্ন নেয় , যেহেতু এবং এর মধ্যে একটি নেতিবাচক মান হয় , এটি অগত্যা কম এবং ধনাত্মক। গত মডিউল আছে ক্ষেত্রে দিয়ে শুরু করতে, যেহেতু যদি ইতিবাচক ছিল ইতিবাচক চেয়ে বড় হয়ে যাবে । অতএব, এটিকে আবার আগের চেয়ে ছোট করে তোলে (এবং নেতিবাচক মানগুলিকে প্রভাবিত করে না )।baba(a % b)-b0(a % b + b)baa(a % b + b)b(a % b + b) % bba


3
এটি আরও ভাল ধন্যবাদ ধন্যবাদ। এবং এটি নেগেটিভ সংখ্যার জন্য কাজ করে যা খ এর চেয়ে অনেক বেশি বড়।
বেড়ান ent

6
এটা তোলে ফল থেকে কাজ করে (a % b)অগত্যা চেয়ে কম b(কোন ব্যাপার যদি aইতিবাচক বা নেতিবাচক হয়) যোগ bনেতিবাচক মূল্যবোধের যত্ন নেয় a, যেহেতু (a % b)কম bএবং কম 0, (a % b + b)অগত্যা চেয়ে কম bএবং ইতিবাচক। গত মডিউল আছে ক্ষেত্রে aদিয়ে শুরু করতে, যেহেতু যদি ইতিবাচক ছিল aইতিবাচক (a % b + b)চেয়ে বড় হয়ে যাবে b। অতএব, (a % b + b) % bএটিকে bআবার আগের চেয়ে ছোট করে তোলে (এবং নেতিবাচক aমানগুলিকে প্রভাবিত করে না )।
ইথানফার

1
@ আইটানফার আমি উত্তরে আপনার দুর্দান্ত ব্যাখ্যাটি অন্তর্ভুক্ত করেছি (এর জন্য একটি সামান্য সংশোধন সহ a < 0, সম্ভবত আপনি একবার দেখতে পারেন)
মার্টেন বোদেউয়েস

5
আমি স্রেফ একই বিষয় সম্পর্কিত আরও একটি প্রশ্নে এই মন্তব্যটি দেখেছি; এটি উল্লেখযোগ্য হতে পারে যে (a % b + b) % bখুব বড় মানের aএবং এর জন্য ভেঙে যায় b। উদাহরণস্বরূপ, ব্যবহার a = Integer.MAX_VALUE - 1এবং ফলাফল হিসাবে b = Integer.MAX_VALUEদেবে -3, যা একটি নেতিবাচক সংখ্যা, যা আপনি এড়াতে চেয়েছিলেন।
থর্বার

2
@ মাইকপোট ব্যবহার whileকরা ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে হুড়োহুদি, যদি আপনার প্রয়োজন হয় তবে ifএটি আসলে দ্রুততর হয়।
পিটার লরি

92

জাভা 8-র হিসাবে, আপনি ম্যাথ.ফ্লুরমড (ইনট এক্স, ইনট y) এবং ম্যাথ.ফ্লোরমড (লং এক্স, লং ওয়াই) ব্যবহার করতে পারেন । এই দুটি পদ্ধতিই পিটারের উত্তর হিসাবে একই ফলাফল দেয়।

Math.floorMod( 2,  3) =  2
Math.floorMod(-2,  3) =  1
Math.floorMod( 2, -3) = -1
Math.floorMod(-2, -3) = -2

1
জাভা 8+ এর সেরা উত্তর
চার্নি কায়ে

দুর্দান্ত, ওটার কথা জানতাম না। জাভা 8 নির্দিষ্টভাবে কয়েকটি পিআইটিএ স্থির করেছে।
ফ্রানজ ডি

4
ভাল পথ. তবে দুর্ভাগ্যক্রমে যুক্তি floatবা doubleতর্ক নিয়ে কাজ করে না । মোড বাইনারি অপারেটর ( %) এছাড়াও কাজ করে floatএবং doubleঅপারেশন করে।
মীর-ইসমাইলি

11

যাঁরা এখনও জাভা 8 ব্যবহার করছেন না (বা ব্যবহার করতে সক্ষম নন) তাদের জন্য পেয়ারা ইন্টমাথ.মোড () নিয়ে উদ্ধার করতে এসেছিল , গুয়ারা ১১.০ এর পরে পাওয়া যায়।

IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1

একটি সতর্কতা: জাভা 8 এর ম্যাথ.ফ্লোরমড () এর বিপরীতে বিভাজক (দ্বিতীয় প্যারামিটার) নেতিবাচক হতে পারে না।


7

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

= এমওডি (-4,180) = 176 = এমওডি (176, 180) = 176

কারণ 180 * (-1) + 176 = -4 180 * 0 + 176 = 176 এর সমান

এখানে ঘড়ির উদাহরণ ব্যবহার করে, http://mathworld.wolfram.com/Congruence.html আপনি সময়কাল_আপনি সময় চক্রের দৈর্ঘ্য -45 মিনিট বলতে পারবেন না, আপনি উভয় উত্তরই বেস সমীকরণকে সন্তুষ্ট করলেও 15 মিনিট বলবেন।


1
সংখ্যার তত্ত্বে এটি সর্বদা ইতিবাচক হয় না ... তারা একত্রিত ক্লাসে পড়ে। আপনার চিহ্নিতকরণের উদ্দেশ্যে আপনি সেই শ্রেণীর যে কোনও প্রার্থীকে বেছে নিতে পারবেন তবে ধারণাটি এই যে এটি সমস্ত শ্রেণীর জন্য মানচিত্র তৈরি করে এবং যদি এটি থেকে কোনও নির্দিষ্ট প্রার্থী ব্যবহার করে একটি নির্দিষ্ট সমস্যা উল্লেখযোগ্যভাবে সরল করে তোলে ( উদাহরণস্বরূপ -1পরিবর্তে নির্বাচন করা n-1) তারপর এটি আছে।
বুক করুন ad

2

জাভা 8 রয়েছে Math.floorMod, তবে এটি খুব ধীর (এর বাস্তবায়নের একাধিক বিভাগ, গুণ এবং শর্তসাপেক্ষ রয়েছে)। এটি সম্ভব যে জেভিএমের এটির জন্য একটি অন্তর্নিহিত অনুকূলিত স্টাব রয়েছে, যা এটি উল্লেখযোগ্যভাবে বাড়িয়ে তুলবে।

এটি ছাড়াই এটির দ্রুততম উপায় floorModহ'ল এখানে অন্যান্য উত্তরগুলির মতো, তবে শর্তযুক্ত কোনও শাখা নেই এবং কেবল একটি ধীর গতি নেই %

ধরে নেওয়া n ইতিবাচক, এবং এক্স কিছু হতে পারে:

int remainder = (x % n); // may be negative if x is negative
//if remainder is negative, adds n, otherwise adds 0
return ((remainder >> 31) & n) + remainder;

ফলাফলগুলি যখন n = 3:

x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
 0| 0
 1| 1
 2| 2
 3| 0
 4| 1

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

return ((x >> 31) & (n - 1)) + (x % n)

উপরেরগুলির জন্য ফলাফলগুলি n = 3:

x | result
----------
-5| 0
-4| 1
-3| 2
-2| 0
-1| 1
 0| 0
 1| 1
 2| 2
 3| 0
 4| 1
 5| 2

যদি ইনপুটটি কোনও পূর্ণ পরিসরে র্যান্ডম হয় তবে দুটি সমাধানের বিতরণ একই হবে be যদি ইনপুট ক্লাস্টার শূন্যের কাছাকাছি n - 1হয় তবে পরবর্তী সমাধানগুলিতে খুব কম ফলাফল আসবে।


1

এখানে একটি বিকল্প:

a < 0 ? b-1 - (-a-1) % b : a % b

এটি অন্য সূত্রের চেয়ে দ্রুত হতে পারে বা নাও হতে পারে [(একটি% বি + বি)% বি]। অন্যান্য সূত্রের বিপরীতে, এটিতে একটি শাখা রয়েছে তবে এটি একটি কম মডুলো অপারেশন ব্যবহার করে। কম্পিউটার যদি কোনও <0 টি সঠিকভাবে ভবিষ্যদ্বাণী করতে পারে তবে সম্ভবত একটি জয়।

(সম্পাদনা করুন: সূত্রটি স্থির করা হয়েছে))


1
তবে মডিউলো অপারেশনটির একটি বিভাগ প্রয়োজন যা আরও ধীর হতে পারে (বিশেষত যদি প্রসেসর প্রায় সব সময় সঠিকভাবে শাখাটি অনুমান করে)। সুতরাং এটি সম্ভবত আরও ভাল।
ডেভ

@KarstenR। তুমি ঠিক! আমি সূত্রটি স্থির করেছি, এখন এটি সূক্ষ্মভাবে কাজ করে (তবে আরও দুটি বিয়োগের প্রয়োজন)।
স্টিফান রেইচ

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