আমি সি # তে স্বাক্ষরবিহীন ইন্ট ব্যবহার করা এড়ানো উচিত?


23

আমি সম্প্রতি সি # তে স্বাক্ষরবিহীন পূর্ণসংখ্যার ব্যবহার সম্পর্কে চিন্তা করেছি (এবং আমার ধারণা অন্যান্য "উচ্চ স্তরের ভাষাগুলি" সম্পর্কেও অনুরূপ যুক্তি বলা যেতে পারে)

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

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

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

এই সমস্যাটি সম্পর্কে কিছু সাধারণ সেরা অভ্যাসগুলি কী কী? এই ধরণের দৃশ্যের সাথে আমার কীভাবে আচরণ করা উচিত?



1
অতিরিক্ত স্বাক্ষরবিহীন ইন্টি সিএলএস অনুবর্তী নয়, যার অর্থ আপনি অন্যান্য। নেট ভাষা থেকে তাদের ব্যবহার করা এমন API গুলি কল করতে পারবেন না।
নাথান কুপার

2
@NathanCooper: ... "API গুলি তাদের কাছ থেকে ব্যবহার কল করতে পারবেন না কিছু অন্যান্য ভাষায়"। তাদের জন্য মেটাডেটা মানক করা হয়েছে, সুতরাং স্বাক্ষরবিহীন প্রকারকে সমর্থন করে এমন সমস্ত .NET ভাষাগুলি ঠিক জরিমানা করবে।
বেন ভয়েগট

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

2
"... তবে এই প্যাটার্নটি আমাকে অনেক ক্লাস তৈরি করতে এবং বিভ্রান্তির উত্স হতে পারে" আসলে এটি করা সঠিক জিনিস। কেবল কুখ্যাত আদিম আবেশ বিরোধী প্যাটার্ন অনুসন্ধান করুন।
গানগো

উত্তর:


24

.NET ফ্রেমওয়ার্কের ডিজাইনাররা বেশ কয়েকটি কারণে 32-বিট স্বাক্ষরিত পূর্ণসংখ্যাকে তাদের "সাধারণ-উদ্দেশ্য সংখ্যা" হিসাবে বেছে নিয়েছেন:

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

স্বাক্ষরবিহীন ints ব্যবহার করার কারণ পাঠযোগ্যতা নয় ; এটি কেবলমাত্র একটি স্বাক্ষরবিহীন ইন্টি সরবরাহ করে এমন গণিত পাওয়ার ক্ষমতা রাখে।

গার্ড ক্লজ, বৈধতা এবং চুক্তির পূর্ব শর্তগুলি বৈধ সংখ্যাযুক্ত ব্যাপ্তিগুলি বীমা করার জন্য নিখুঁতভাবে গ্রহণযোগ্য উপায়। কদাচিৎ একটি আসল-বিশ্বসংখ্যার পরিসীমা শূন্য এবং 2 32 -1 এর মধ্যে সংখ্যার সাথে ঠিক মিল করে (বা আপনি যে জাতীয় সংখ্যাটি পছন্দ করেন তা সংখ্যার ধরণের যাই হোক না কেন), সুতরাং uintআপনার ইন্টারফেস চুক্তিকে ইতিবাচক সংখ্যায় সীমাবদ্ধ করতে একটি ব্যবহার করা এক রকম বিন্দুর পাশে.


2
চমৎকার উত্তর! এছাড়াও এমন কিছু ক্ষেত্রে থাকতে পারে যেখানে একটি স্বাক্ষরবিহীন ইন্টি আসলে অসাবধানতাবশত আরও ত্রুটি তৈরি করতে পারে (যদিও এটিগুলি সাথে সাথে চিহ্নিত করা হয়েছে তবে কিছুটা বিভ্রান্তিকর) - স্বাক্ষরযুক্ত স্বাক্ষরযুক্ত কাউন্টারটির সাথে বিপরীতে লুপিংয়ের কথা কল্পনা করুন কারণ কিছু আকার একটি পূর্ণসংখ্যা: for (uint j=some_size-1; j >= 0; --j)- ওফস ( এটি সি # তে কোনও সমস্যা কিনা তা নিশ্চিত নন)! আমি কোডটিতে এই সমস্যাটি খুঁজে পেয়েছি যার আগে সি পার্শ্বে যতটা সম্ভব স্বাক্ষরবিহীন ইনট ব্যবহার করার চেষ্টা করা হয়েছিল - এবং আমরা intপরে এটির পক্ষে পরিবর্তন করে শেষ করেছি এবং কম সংকলক সতর্কতা সহ আমাদের জীবনও অনেক সহজ ছিল।

14
"কদাচিৎ একটি বাস্তব-বিশ্বের সংখ্যার পরিসীমা শূন্য এবং 2 ^ 32-1 এর মধ্যে সংখ্যার সাথে মিল করে" " আমার অভিজ্ঞতায়, যদি আপনার 2 ^ 31 এর চেয়ে বড় সংখ্যার প্রয়োজন হয় তবে আপনার খুব সম্ভবত 2 ^ 32 এর চেয়েও বড় সংখ্যার প্রয়োজন হবে, সুতরাং আপনি কেবলমাত্র স্বাক্ষরিত ইন্টুআর 64-এ সরে যেতে পারেন যে বিন্দু।
ম্যাসন হুইলারের

3
@ পানজারক্রিসিস: এটি কিছুটা গুরুতর। এটা সম্ভবত আরো কিছু বলতে নির্ভুল হবে "ব্যবহার করুন intঅধিকাংশ সময় কারণ যে প্রতিষ্ঠিত সম্মেলন, এবং এটা অধিকাংশ লোক নিয়মিতভাবে ব্যবহার দেখতে আশা কি যাচ্ছি না। ব্যবহারের uintযখন আপনি একটি বিশেষ কর্মক্ষমতা প্রয়োজন uint।" মনে রাখবেন, ফ্রেমওয়ার্ক ডিজাইনাররা এই কনভেনশনটি ব্যাপকভাবে অনুসরণ করার সিদ্ধান্ত নিয়েছে, তাই আপনি uintঅনেকগুলি ফ্রেমওয়ার্ক প্রসঙ্গে (এটি টাইপ-সামঞ্জস্যপূর্ণ নয়) ব্যবহার করতে পারবেন না ।
রবার্ট হার্ভে

2
@ পানজারিক্রিসিস এটি অত্যধিক শক্তিশালী ফ্রেসিং হতে পারে; তবে আমি নিশ্চিত না যে আমি কখনই সি # তে স্বাক্ষরযুক্ত প্রকারগুলি ব্যবহার করেছি যখন আমি উইন 32 এপিএস (যেখানে কনভেনশনটি কনস্ট্যান্টস / ফ্ল্যাগস / ইত্যাদি স্বাক্ষরবিহীন থাকে) নাম্বারে ডেকে আছি।
ড্যান নীলি

4
এটা সত্যিই খুব বিরল। আমি কখনই স্বাক্ষরবিহীন ইনটগুলি ব্যবহার করি কেবলমাত্র বিট-টুইডলিংয়ের পরিস্থিতিতে।
রবার্ট হারভে

8

সাধারণত, আপনার ডেটা সম্ভব হওয়ার জন্য আপনার সর্বদা সুনির্দিষ্ট ডেটা টাইপ ব্যবহার করা উচিত।

উদাহরণস্বরূপ, আপনি যদি কোনও ডাটাবেস থেকে ডেটা টানতে সত্ত্বা ফ্রেমওয়ার্ক ব্যবহার করছেন, EF স্বয়ংক্রিয়ভাবে ডেটাবেজে ব্যবহৃত একের নিকটবর্তী ডেটা টাইপটি ব্যবহার করবে।

সি # তে এটি নিয়ে দুটি সমস্যা রয়েছে।
প্রথমত, বেশিরভাগ সি # বিকাশকারী intপুরো সংখ্যাটি উপস্থাপন করতে (কেবলমাত্র ব্যবহারের কারণ না থাকলে long) ব্যবহার করেন । এর অর্থ হ'ল অন্যান্য বিকাশকারীরা ডেটা প্রকারটি পরীক্ষা করতে ভাবেন না, তাই তারা উপরে উল্লিখিত ওভারফ্লো ত্রুটিগুলি পাবেন। দ্বিতীয়, এবং আরও জটিল সমস্যা হল, / ছিল .NET এর মূল গাণিতিক অপারেটর শুধুমাত্র সমর্থিত int, uint, long, ulong, float, ডবল, এবং decimal*। এটি আজও একই অবস্থানে রয়েছে ( সি # 5.0 ভাষার ক্ষেত্রে অনুচ্ছেদ 7.8.4 দেখুন )। আপনি নিম্নলিখিত কোডটি ব্যবহার করে নিজে এটি পরীক্ষা করতে পারেন:

byte a, b;
a = 1;
b = 2;
var c = a - b;      //In visual studio, hover over "var" and the tip will indicate the data type, or you can get the value from cName below.
string cName = c.GetType().Namespace + '.' + c.GetType().Name;

আমাদের byte- এর ফলাফল byteএকটি int( System.Int32)।

এই দুটি সমস্যা "সম্পূর্ণ সংখ্যার জন্য কেবলমাত্র ব্যবহারের" অনুশীলনের জন্ম দিয়েছে যা এত সাধারণ so

সুতরাং আপনার প্রশ্ন, এ সি # এটি সাধারণত বিদ্ধ করা একটি ভাল ধারণা উত্তর দিতে intযদি না:

  • একটি স্বয়ংক্রিয় কোড জেনারেটর একটি আলাদা মান ব্যবহার করেছে (যেমন সত্তা ফ্রেমওয়ার্ক)।
  • প্রকল্পের অন্য সমস্ত বিকাশকারী সচেতন যে আপনি কম সাধারণ ডেটা প্রকারগুলি ব্যবহার করছেন (আপনি কীভাবে ডেটা ব্যবহার করেছেন এবং কেন ব্যবহার করেছেন তা নির্দেশ করে একটি মন্তব্য অন্তর্ভুক্ত করুন)।
  • কম সাধারণ তথ্য প্রকারগুলি ইতিমধ্যে প্রকল্পে সাধারণত ব্যবহৃত হয়।
  • প্রোগ্রামটির জন্য কম প্রচলিত ডেটা টাইপের সুবিধাগুলি প্রয়োজন (আপনার এগুলির মধ্যে আপনার 100 মিলিয়ন র‌্যাম রাখতে হবে, সুতরাং একটি byteএবং একটি intবা একটি intএবং এর মধ্যে পার্থক্যটি longসমালোচক, বা ইতিমধ্যে উল্লিখিত স্বাক্ষরযুক্ত পাটিগণিতের পার্থক্য)।

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

enumউপরোক্ত নির্দেশিকাগুলিতে আমার ব্যক্তিগত ব্যতিক্রমগুলির মধ্যে এনুমারেশনগুলি ( )। আমার কাছে যদি কেবল কয়েকটি বিকল্প থাকে তবে আমি এনামকে বাইট বা সংক্ষিপ্ত হিসাবে নির্দিষ্ট করব । যদি আমার পতাকাঙ্কিত এনুমে শেষ বিটটি লাগে তবে আমি প্রকারটি নির্দিষ্ট করে করব uintযাতে আমি হেক্স ব্যবহার করে পতাকাটির মান নির্ধারণ করতে পারি।

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

* নেট # এর পরিবর্তে সি # এলিয়াস ব্যবহার করা হয় System.Int32কারণ এটি একটি সি # প্রশ্ন।

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

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


আমার থাম্বের সাধারণ নিয়মটি হ'ল "ইনট ব্যবহার করুন, আপনি না পারলে"।
পেরিসি

@ পেরিসি আমি বিশ্বাস করি যে এটি সবচেয়ে সাধারণ সম্মেলন common আমার উত্তরের বিষয়টি হ'ল একটি আরও সম্পূর্ণ কনভেনশন সরবরাহ করা যা আপনাকে ভাষার বৈশিষ্ট্যগুলি ব্যবহার করতে দেয়।
ট্রাইপড

6

আপনার প্রধানত দুটি জিনিস সম্পর্কে সচেতন হওয়া দরকার: আপনি যে ডেটা উপস্থাপন করছেন তা এবং আপনার গণনার কোনও মধ্যবর্তী পদক্ষেপ।

বয়সের হওয়ার বিষয়টি অবশ্যই বোধগম্য unsigned int, কারণ আমরা সাধারণত নেতিবাচক বয়স বিবেচনা করি না। তবে তারপরে আপনি এক বয়স থেকে অন্য বয়সকে বিয়োগ করার কথা উল্লেখ করেছেন। যদি আমরা কেবল অন্ধভাবে অন্যের থেকে একটি পূর্ণসংখ্যা বিয়োগ করি তবে অবশ্যই ইতিমধ্যে একটি নেতিবাচক সংখ্যার সাথে সমাপ্তি সম্ভব, এমনকি যদি আমরা ইতিপূর্বে সম্মত হয়েছি যে নেতিবাচক বয়সগুলি অর্থপূর্ণ নয়। সুতরাং এক্ষেত্রে আপনি চাইবেন আপনার গণনাটি একটি স্বাক্ষরিত পূর্ণসংখ্যার সাথে করা হবে।

স্বাক্ষরযুক্ত স্বীকৃত মানগুলি খারাপ কিনা সে সম্পর্কে আমি বলব যে স্বাক্ষরযুক্ত মানগুলি খারাপ বলে এটি একটি বিশাল সাধারণীকরণ। জাভাতে স্বাক্ষরবিহীন মান নেই, যেমনটি আপনি উল্লেখ করেছেন এবং এটি আমাকে ক্রমাগত বিরক্ত করে। একজন byte0-255 বা 0x00-0xFF থেকে একটি মান থাকতে পারে। তবে আপনি যদি 127 (0x7F) এর চেয়ে বড় বাইটটি ইনস্ট্যান্ট করতে চান তবে আপনাকে এটি negativeণাত্মক সংখ্যা হিসাবে লিখতে হবে বা একটি বাইটে একটি পূর্ণসংখ্যা কাস্ট করতে হবে। আপনি এমন কোড সহ শেষ করেন যা দেখতে দেখতে:

byte a = 0x80; // Won't compile!
byte b = (byte) 0x80;
byte c = -128; // Equal to b

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

byte a = 70;
byte b = 80;
byte c = a + b; // c == -106

সুতরাং আপনি যেমন দেখতে পাচ্ছেন, বৈধ মান সহ দুটি বাইট যুক্ত করা এবং একটি বৈধ মান সহ একটি বাইট সহ শেষ হওয়া সাইন পরিবর্তন করে। কেবল তা-ই নয় তবে এটি তাত্ক্ষণিকভাবে স্পষ্ট নয় যে 70 + 80 == -106। প্রযুক্তিগতভাবে এটি একটি ওভারফ্লো, তবে আমার মনে (মানুষ হিসাবে) বাইটটি 0xFF এর অধীন মানগুলির জন্য উপচে পড়া উচিত নয়। আমি যখন কাগজে বিট পাটিগণিত করি, আমি 8 তম বিটকে একটি চিহ্ন বিট হিসাবে বিবেচনা করি না।

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

signed byte b = 0b10000000;
b = b >> 1; // b == 0b1100 0000
b = b & 0x7F;// b == 0b0100 0000

unsigned byte b = 0b10000000;
b = b >> 1; // b == 0b0100 0000;

এটি কেবলমাত্র অতিরিক্ত পদক্ষেপ যুক্ত করে যা আমার মনে হয় যে প্রয়োজনীয় হওয়া উচিত নয়।

আমি byteউপরে ব্যবহার করার সময় , একইটি 32-বিট এবং 64-বিট পূর্ণসংখ্যার ক্ষেত্রে প্রযোজ্য। না থাকা unsignedপঙ্গু হচ্ছে না এবং এটি আমাকে স্তম্ভিত করে যে জাভা এর মতো উচ্চ স্তরের ভাষা রয়েছে যা তাদের একেবারেই অনুমতি দেয় না। তবে বেশিরভাগ মানুষের কাছে এটি একটি নন-ইস্যু, কারণ অনেক প্রোগ্রামার বিট-লেভেল পাটিগণিত নিয়ে কাজ করেন না।

শেষ পর্যন্ত, স্বাক্ষরযুক্ত পূর্ণসংখ্যাগুলি ব্যবহার করার জন্য দরকারী যদি আপনি সেগুলি বিট হিসাবে ভেবে থাকেন এবং যখন আপনি সংখ্যা হিসাবে ভেবেছেন তখন স্বাক্ষরিত পূর্ণ সংখ্যাগুলি ব্যবহার করা দরকারী useful


7
আমি স্বাক্ষরবিহীন ইন্টিগ্রাল ধরণের (বিশেষত বাইটের জন্য) ভাষা না নিয়ে ভাষা সম্পর্কে আপনার হতাশাগুলি ভাগ করি তবে আমি ভয় করি যে এটি এখানে জিজ্ঞাসিত প্রশ্নের সরাসরি উত্তর নয়। হতে পারে আপনি একটি উপসংহার যোগ করতে পারেন, যা আমি বিশ্বাস করি, এটি হতে পারে: "আপনি স্বাক্ষরযুক্ত পূর্ণসংখ্যাগুলি ব্যবহার করুন যদি আপনি তাদের সংখ্যা হিসাবে বিট এবং স্বাক্ষরিত পূর্ণসংখ্যার হিসাবে ভেবে থাকেন তবে আপনি তাদের সংখ্যা হিসাবে চিন্তা করছেন।"
5gon12eder

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