স্বাক্ষরবিহীন পূর্ণসংখ্যার বিয়োগটি সংজ্ঞাযুক্ত আচরণ?


104

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

unsigned int To, Tf;

To = getcounter();
while (1) {
    Tf = getcounter();
    if ((Tf-To) >= TIME_LIMIT) {
        break;
    } 
}

আমি খুঁজে পেতে পারে এটি সি স্ট্যান্ডার্ডের একমাত্র অস্পষ্ট প্রাসঙ্গিক উদ্ধৃতি।

স্বাক্ষরবিহীন অপারেন্ডগুলির সাথে জড়িত কোনও গণনা কখনই ow over over because over uns can। Can can can can can because because because because because because because because because because because igned igned igned igned igned uns

আমি মনে করি যে কেউ এই অর্থটি গ্রহণ করতে পারে যে ডান অপরেন্ড বড় হলে অপারেশনটি মডুলো কাটা সংখ্যার প্রেক্ষাপটে অর্থবহ হিসাবে সমন্বিত হয়।

অর্থাত্

0x0000 - 0x0001 == 0x 1 0000 - 0x0001 == 0xFFFF

বাস্তবায়ন নির্ভর স্বাক্ষরিত শব্দার্থক ব্যবহারের বিপরীতে:

0x0000 - 0x0001 == (স্বাক্ষরযুক্ত) (0 + -1) == (0xFFFF তবে 0xFFFE বা 0x8001)

কোনটি বা কোন ব্যাখ্যাটি সঠিক? এটা আদৌ সংজ্ঞায়িত করা হয়?


4
স্ট্যান্ডার্ড শব্দের পছন্দ দুর্ভাগ্যজনক। এটি "কখনই উপচে পড়তে পারে না" এর অর্থ এটি ত্রুটির পরিস্থিতি নয়। স্ট্যান্ডোলজিটি স্ট্যান্ডার্ডে ব্যবহার করে পরিবর্তিত মানের পরিবর্তে "মোড়ানো"।
ড্যানরটন

উত্তর:


110

স্বাক্ষরবিহীন প্রকারে নেতিবাচক সংখ্যা উত্পন্ন বিয়োগের ফলাফলটি সঠিকভাবে সংজ্ঞায়িত হয়েছে:

  1. [...] স্বাক্ষরযুক্ত অপারেটসগুলির সাথে জড়িত কোনও গণনা কখনই উপচে পড়তে পারে না, কারণ ফলাফল স্বাক্ষরযুক্ত পূর্ণসংখ্যার ধরণের দ্বারা প্রতিনিধিত্ব করা যায় না এমন ফলাফলটি মোডুলো হ্রাস করা হয় যা ফলাফলের ধরণের দ্বারা প্রতিনিধিত্ব করা যায় এমন বৃহত্তম মানের চেয়ে বড়। (আইএসও / আইইসি 9899: 1999 (ই) §6.2.5 / 9)

আপনি দেখতে পাচ্ছেন, (unsigned)0 - (unsigned)1সমান -1 মডুলো UINT_MAX + 1, বা অন্য কথায়, UINT_MAX।

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


4
ধন্যবাদ! আমি এখন আমি যে ব্যাখ্যাটি অনুপস্থিত ছিল তা দেখছি। আমি মনে করি তারা যদিও আরও পরিষ্কার শব্দটি বেছে নিতে পারত।

4
আমি এত এখন ভাল বোধ করছেন, বুদ্ধিমান যে যদি শূন্য কোনো স্বাক্ষরবিহীন উপরন্তু রোলস প্রায় এবং মারপিট কারণ, কারণ হবে uintসবসময় গাণিতিক প্রতিনিধিত্ব করতে জন্যই ছিল রিং পূর্ণসংখ্যার 0মাধ্যমে UINT_MAXউপরন্তু এবং গুণ মডিউল অভিযান সঙ্গে, UINT_MAX+1এবং না কারণ একটি উপচে পড়া তবে এটি এই প্রশ্নটি করে, কেন রিংগুলি যদি এমন মৌলিক ডেটা টাইপ হয় তবে ভাষা অন্যান্য মাপের রিংয়ের জন্য আরও সাধারণ সমর্থন সরবরাহ করে না।
থিওডোর মুরডক

4
@ থিওডোরমুরডক আমি মনে করি যে এই প্রশ্নের উত্তর সহজ is আমি যতদূর বলতে পারি যে এটি একটি আংটি একটি ফলাফল, কারণ নয়। আসল প্রয়োজন হ'ল স্বাক্ষরযুক্ত প্রকারের তাদের সমস্ত বিটকে মান উপস্থাপনায় অংশ নিতে হবে। রিং-এর মতো আচরণটি প্রাকৃতিকভাবে সেখান থেকে প্রবাহিত হয়। আপনি যদি অন্য ধরণের থেকে এ জাতীয় আচরণ চান, তবে প্রয়োজনীয় গাণিতিক প্রয়োগ করে আপনার গাণিতিকটি করুন; যে মৌলিক অপারেটর ব্যবহার করে।
আন্ডারস্কোর_

@ আসর_আর_ অবশ্যই ... তারা কেন নকশার সিদ্ধান্ত নিয়েছে তা স্পষ্ট। এটি কেবল মজাদার যে তারা "স্পষ্টতই" গাণিতিকের উপরে / আন্ডারফ্লোতে কোনও গাণিতিক নেই কারণ ডেটা টাইপটি একটি রিং হিসাবে নির্দিষ্ট করা হয় "হিসাবে এই নকশার পছন্দটি মানে প্রোগ্রামারদের সাবধানতার সাথে এড়াতে হবে না - এবং এর অধীনে প্রবাহিত বা তাদের প্রোগ্রাম দর্শনীয়ভাবে ব্যর্থ হয়েছে।
থিওডোর মুরডক

122

আপনি স্বাক্ষরবিহীন প্রকারের সাথে কাজ করার সময় , মডুলার গাণিতিক ( "র্যাপের আশেপাশে" আচরণ হিসাবেও পরিচিত ) ঘটে চলেছে। এই মডুলার গাণিতিকটি বুঝতে , এই ঘড়িগুলি একবার দেখুন:

এখানে চিত্র বর্ণনা লিখুন

9 + 4 = 1 ( 13 মড 12 ), তাই অন্য দিকটি এটি: 1 - 4 = 9 ( -3 মড 12 )। স্বাক্ষরবিহীন প্রকারের সাথে কাজ করার সময় একই নীতি প্রয়োগ করা হয়। যদি ফলাফলের ধরণ হয় unsignedতবে মডুলার গাণিতিক স্থান নেয়।


ফলাফল হিসাবে ফলাফল সংরক্ষণ করে এখন নিম্নলিখিত অপারেশনগুলি দেখুন unsigned int:

unsigned int five = 5, seven = 7;
unsigned int a = five - seven;      // a = (-2 % 2^32) = 4294967294 

int one = 1, six = 6;
unsigned int b = one - six;         // b = (-5 % 2^32) = 4294967291

আপনি যখন ফলাফলটি নিশ্চিত করতে চান signedতবে তা এটিকে signedভেরিয়েবেলে সংরক্ষণ করুন বা এতে castালাই করুন signed। আপনি যখন সংখ্যার মধ্যে পার্থক্য পেতে চান এবং তা নিশ্চিত করতে চান যে মডিউলার গাণিতিক প্রয়োগ করা হবে না, তখন আপনাকে এতে abs()সংজ্ঞায়িত ফাংশনটি ব্যবহার করে বিবেচনা করা উচিত stdlib.h:

int c = five - seven;       // c = -2
int d = abs(five - seven);  // d =  2

বিশেষত শর্ত লেখার সময় খুব সাবধান থাকুন কারণ:

if (abs(five - seven) < seven)  // = if (2 < 7)
    // ...

if (five - seven < -1)          // = if (-2 < -1)
    // ...

if (one - six < 1)              // = if (-5 < 1)
    // ...

if ((int)(five - seven) < 1)    // = if (-2 < 1)
    // ...

কিন্তু

if (five - seven < 1)   // = if ((unsigned int)-2 < 1) = if (4294967294 < 1)
    // ...

if (one - six < five)   // = if ((unsigned int)-5 < 5) = if (4294967291 < 5)
    // ...

4
ঘড়িগুলির সাথে একটি দুর্দান্ত, যদিও প্রমাণ এটির সঠিক উত্তর দেয়। প্রশ্নের ভিত্তি ইতিমধ্যে এই সমস্ত সত্য হতে পারে যে দাবী অন্তর্ভুক্ত।
অরবিটে লাইটনেস রেস

5
@ লাইটনেসেসেসিন অরবিত: আপনাকে ধন্যবাদ আমি এটি লিখেছিলাম কারণ আমি মনে করি যে কেউ এটি খুব সহায়ক বলে মনে করতে পারে। আমি একমত, এটি সম্পূর্ণ উত্তর নয় answer
LihO

4
লাইন int d = abs(five - seven);ভাল না। প্রথমত five - sevenগণনা করা হয়: প্রচার অপারেন্ডের ধরণগুলি যেমন ছেড়ে দেয় unsigned int, ফলাফলটি গণনা করা মডুলো হয় (UINT_MAX+1)এবং এতে মূল্যায়ন হয় UINT_MAX-1। তারপরে এই মানটি হ'ল আসল প্যারামিটার absযা খারাপ খবর। abs(int)আর্গুমেন্টটি অপরিবর্তিত আচরণের কারণ হয়ে থাকে, যেহেতু এটি সীমার মধ্যে নেই, এবং abs(long long)সম্ভবত এটি মানটি ধরে রাখতে পারে, তবে ফেরতের মানটি intআরম্ভ করতে বাধ্য করা হলে অপরিজ্ঞাত আচরণ হয় d
বেন ভয়েগট

4
@ লিহো: সি ++ এর একমাত্র অপারেটর যা প্রসঙ্গ-সংবেদনশীল এবং এর ফলাফল কীভাবে ব্যবহৃত হয় তার উপর নির্ভর করে ভিন্নভাবে কাজ করে এটি একটি কাস্টম রূপান্তর অপারেটর operator T()। আমরা যে দুটি এক্সপ্রেশন নিয়ে আলোচনা করছি তাতে সংযোজন unsigned intঅপারেন্ডের ধরণের ভিত্তিতে টাইপ করা হয়। সংযোজন ফলাফল unsigned int। তারপরে ফলাফলটি প্রাসঙ্গিকভাবে প্রয়োজনীয় প্রকারে স্পষ্টভাবে রূপান্তরিত হয়, একটি রূপান্তর যা ব্যর্থ হয় কারণ মানটি নতুন ধরণের ক্ষেত্রে উপস্থাপনযোগ্য নয়।
বেন ভয়েগট

4
@ লিহো: এটি double x = 2/3;বনাম সম্পর্কে ভাবতে সহায়তা করতে পারেdouble y = 2.0/3;
বেন ভয়েগট

5

ঠিক আছে, প্রথম ব্যাখ্যাটি সঠিক। তবে এই প্রসঙ্গে "স্বাক্ষরিত শব্দার্থবিজ্ঞান" সম্পর্কে আপনার যুক্তিটি ভুল।

আবার আপনার প্রথম ব্যাখ্যাটি সঠিক is স্বাক্ষরবিহীন গাণিতিকগুলি মডুলো গাণিতিকের নিয়ম অনুসরণ করে, যার অর্থ 32-বিট স্বাক্ষরযুক্ত প্রকারের জন্য 0x0000 - 0x0001মূল্যায়ন করে 0xFFFF

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

উদাহরণস্বরূপ, এই মূল্যায়ন

signed int a = 0, b = 1;
unsigned int c = a - b;

এখনও উত্পাদন করতে নিশ্চিত করা হয় UINT_MAXযে c, এমনকি যদি প্ল্যাটফর্ম স্বাক্ষরিত পূর্ণসংখ্যার একটি বহিরাগত উপস্থাপনা ব্যবহার করছে।


4
আমি মনে করি আপনি 16 বিট স্বাক্ষরযুক্ত প্রকারের অর্থ 32 বিট নয় not
xioxox 10

4

স্বাক্ষরযুক্ত স্বাক্ষরযুক্ত সংখ্যার unsigned intবা তার বেশি সংখ্যার সাথে , ধরণের রূপান্তরগুলির অভাবে, a-bস্বাক্ষরযুক্ত সংখ্যাটি ফলন হিসাবে সংজ্ঞায়িত করা হয়, যা যুক্ত হওয়ার পরে b, ফলন হবে a। স্বাক্ষরযুক্ত নেগেটিভ সংখ্যার রূপান্তরটি সংখ্যার ফলন হিসাবে সংজ্ঞায়িত করা হয় যা সাইন-বিপরীত মূল সংখ্যায় যুক্ত হলে শূন্য হবে (সুতরাং -5 স্বাক্ষরিত রূপান্তরিত করে এমন একটি মান আসবে যা 5-এ যুক্ত হলে শূন্য হবে) ।

নোট করুন যে স্বাক্ষরযুক্ত এর চেয়ে কম ছোট সংখ্যাগুলি বিয়োগের আগে unsigned intটাইপ করতে প্রচার হতে পারে int, এর আচরণ a-bআকারের উপর নির্ভর করবে int

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