मैं एक फ़ंक्शन को परिभाषित करना चाहता हूं जो unsigned int
तर्क के रूप में लेता है और तर्क के लिए एक int
अनुरूप मॉड्यूल UINT_MAX + 1 देता है।
पहला प्रयास इस तरह दिख सकता है:
int unsigned_to_signed(unsigned n)
{
return static_cast<int>(n);
}
लेकिन जैसा कि किसी भी भाषा के वकील को पता है, INT_MAX से बड़े मूल्यों के लिए हस्ताक्षरित अहस्ताक्षरित से कास्टिंग कार्यान्वयन-परिभाषित है।
मैं इसे इस तरह लागू करना चाहता हूं कि (ए) यह केवल कल्पना के आधार पर व्यवहार पर निर्भर करता है; और (बी) यह किसी भी आधुनिक मशीन पर नो-ऑप में संकलित करता है और संकलक का अनुकूलन करता है।
जैसा कि विचित्र मशीनों के लिए ... यदि कोई हस्ताक्षरित int conuuent modulo UINT_MAX + 1 बिना हस्ताक्षरित int के नहीं है, तो मान लीजिए कि मैं एक अपवाद फेंकना चाहता हूं। यदि एक से अधिक है (मुझे यकीन नहीं है कि यह संभव है), मान लें कि मैं सबसे बड़ा चाहता हूं।
ठीक है, दूसरा प्रयास:
int unsigned_to_signed(unsigned n)
{
int int_n = static_cast<int>(n);
if (n == static_cast<unsigned>(int_n))
return int_n;
// else do something long and complicated
}
जब मैं अपनी विनम्र राय नहीं लेता हूं, तब से मैं एक विशिष्ट दो-पूरक प्रणाली पर नहीं हूं, मैं दक्षता के बारे में ज्यादा परवाह नहीं करता हूं। और अगर मेरा कोड 2050 के सर्वव्यापी संकेत-परिमाण प्रणालियों पर एक अड़चन बन जाता है, तो, मुझे यकीन है कि कोई व्यक्ति इसका पता लगा सकता है और फिर इसे अनुकूलित कर सकता है।
अब, यह दूसरा प्रयास जो मैं चाहता हूं, उसके बहुत करीब है। यद्यपि int
कुछ इनपुट के लिए कलाकारों को कार्यान्वयन-परिभाषित किया जाता है, फिर unsigned
भी मानक मॉडुलो UINT_MAX + 1 को संरक्षित करने के लिए मानक द्वारा गारंटी दी जाती है। तो सशर्त ठीक वही जांचता है जो मैं चाहता हूं, और यह किसी भी प्रणाली पर कुछ भी संकलित करेगा, जिसकी मुझे मुठभेड़ की संभावना है।
हालाँकि ... मैं अभी भी int
पहली जाँच के बिना कास्टिंग कर रहा हूँ कि क्या यह कार्यान्वयन-परिभाषित व्यवहार को लागू करेगा। 2050 में कुछ काल्पनिक प्रणाली पर यह कर सकता था कि कौन जानता है-क्या। तो चलिए बताते हैं कि मैं इससे बचना चाहता हूं।
प्रश्न: मेरा "तीसरा प्रयास" कैसा दिखना चाहिए?
पुनरावृत्ति करने के लिए, मैं चाहता हूं:
- अहस्ताक्षरित int से हस्ताक्षरित int कास्ट करें
- मान mod UINT_MAX + 1 को संरक्षित करें
- केवल मानक-अनिवार्य व्यवहार लागू करें
- संकलक के अनुकूलन के साथ एक विशिष्ट दो-पूरक मशीन पर एक नो-ऑप में संकलित करें
[अपडेट करें]
मुझे यह दिखाने के लिए एक उदाहरण दें कि यह एक तुच्छ प्रश्न क्यों नहीं है।
निम्नलिखित गुणों के साथ एक काल्पनिक C ++ कार्यान्वयन पर विचार करें:
sizeof(int)
बराबर ४sizeof(unsigned)
बराबर ४INT_MAX
बराबर 32767INT_MIN
बराबर -2 32 + 32768UINT_MAX
बराबर 2 32 - 1- अंकगणित
int
मोडुलो 2 32 (सीमा केINT_MIN
माध्यम सेINT_MAX
) में है std::numeric_limits<int>::is_modulo
सच हैंn
Int के लिए अहस्ताक्षरित कास्टिंग 0 <= n <= 32767 के लिए मान को संरक्षित करता है और अन्यथा शून्य देता है
इस काल्पनिक कार्यान्वयन पर, int
प्रत्येक unsigned
मान के लिए एक मूल्य अनुरूप (mod UINT_MAX + 1) है । तो मेरा सवाल अच्छी तरह से परिभाषित किया जाएगा।
मेरा दावा है कि यह काल्पनिक C ++ कार्यान्वयन पूरी तरह से C ++ 98, C ++ 03 और C ++ 11 विनिर्देशों के अनुरूप है। मैं मानता हूं कि मैंने उन सभी के प्रत्येक शब्द को याद नहीं किया है ... लेकिन मेरा मानना है कि मैंने संबंधित अनुभागों को ध्यान से पढ़ा है। इसलिए यदि आप चाहते हैं कि मैं आपके उत्तर को स्वीकार करूं, तो आपको या तो (क) एक युक्ति का हवाला देना चाहिए जो इस काल्पनिक कार्यान्वयन को नियंत्रित करता है या (ख) इसे सही ढंग से संभालता है।
वास्तव में, एक सही उत्तर को मानक द्वारा अनुमत प्रत्येक काल्पनिक कार्यान्वयन को संभालना चाहिए । यह परिभाषा के अनुसार "केवल मानक-अनिवार्य व्यवहार को लागू करना" है।
संयोग से, ध्यान दें कि std::numeric_limits<int>::is_modulo
कई कारणों से यहाँ बिल्कुल बेकार है। एक बात के लिए, यह तब true
भी हो सकता है जब बिना हस्ताक्षरित जातियां बड़े अहस्ताक्षरित मूल्यों के लिए काम न करें। दूसरे के लिए, यह किसी के true
पूरक या संकेत-परिमाण प्रणाली पर भी हो सकता है , अगर अंकगणित केवल संपूर्ण पूर्णांक सीमा को मापता है। और इसी तरह। यदि आपका उत्तर निर्भर करता है is_modulo
, तो यह गलत है।
[अपडेट २]
hvd के उत्तर ने मुझे कुछ सिखाया: पूर्णांक के लिए मेरा काल्पनिक C ++ कार्यान्वयन आधुनिक सी द्वारा अनुमति नहीं है । C99 और C11 मानक हस्ताक्षरित पूर्णांक के प्रतिनिधित्व के बारे में बहुत विशिष्ट हैं; वास्तव में, वे केवल दो-पूरक, लोगों के पूरक, और साइन-परिमाण (खंड 6.2.6.2 पैरा (2);) की अनुमति देते हैं)।
लेकिन सी ++ सी नहीं है। जैसा कि यह पता चला है, यह तथ्य मेरे सवाल के बहुत दिल में है।
मूल C ++ 98 मानक बहुत पुराने C89 पर आधारित था, जो कहता है (अनुभाग 3.1.2.5):
हस्ताक्षर किए गए पूर्णांक प्रकारों में से प्रत्येक के लिए, एक समान (लेकिन अलग) अहस्ताक्षरित पूर्णांक प्रकार (कीवर्ड के साथ निर्दिष्ट) होता है जो समान मात्रा में संग्रहण (साइन जानकारी सहित) का उपयोग करता है और इसकी संरेखण आवश्यकताएं समान होती हैं। एक हस्ताक्षरित पूर्णांक प्रकार के nonnegative मानों की सीमा संबंधित अहस्ताक्षरित पूर्णांक प्रकार की एक व्यवस्था है, और प्रत्येक प्रकार में समान मूल्य का प्रतिनिधित्व समान है।
C89 का कहना है कि केवल एक साइन बिट या केवल दो-पूरक / लोगों-पूरक / साइन-परिमाण की अनुमति देने के बारे में कुछ नहीं है।
C ++ 98 मानक ने इस भाषा को लगभग शब्दशः (धारा 3.9.1 पैराग्राफ (3)) को अपनाया:
हस्ताक्षर किए गए पूर्णांक प्रकारों में से प्रत्येक के लिए, एक समान (लेकिन अलग) अहस्ताक्षरित पूर्णांक प्रकार मौजूद होता है : "
unsigned char
", "unsigned short int
", "unsigned int
", और "unsigned long int
", जिनमें से प्रत्येक में समान मात्रा में भंडारण होता है और समान संरेखण आवश्यकताएं होती हैं (3.9 ) संबंधित हस्ताक्षरित पूर्णांक प्रकार के रूप में; वह है, प्रत्येक हस्ताक्षरित पूर्णांक प्रकार का एक ही वस्तु प्रतिनिधित्व है जो इसके संबंधित अहस्ताक्षरित पूर्णांक प्रकार के समान है। एक हस्ताक्षरित पूर्णांक प्रकार के nonnegative मानों की सीमा संबंधित अहस्ताक्षरित पूर्णांक प्रकार की एक व्यवस्था है, और प्रत्येक संबंधित हस्ताक्षरित / अहस्ताक्षरित प्रकार का मूल्य प्रतिनिधित्व समान होगा।
C ++ 03 मानक अनिवार्य रूप से समान भाषा का उपयोग करता है, जैसा कि C ++ 11 करता है।
कोई मानक C ++ युक्ति किसी भी C युक्ति में अपने हस्ताक्षरित पूर्णांक निरूपणों में बाधा नहीं डालती, जहाँ तक मैं बता सकता हूँ। और एक भी संकेत बिट या किसी भी तरह का कुछ भी अनिवार्य नहीं है। सभी का कहना है कि गैर-नकारात्मक हस्ताक्षरित पूर्णांक, संबंधित अहस्ताक्षरित की एक व्यवस्था होनी चाहिए।
तो, फिर से मेरा दावा है कि INT_MAX = 32767 INT_MIN = -2 32 +32768 के साथ अनुमति है। यदि आपका उत्तर अन्यथा माना जाता है, तो यह गलत है जब तक कि आप C ++ मानक का हवाला नहीं देते, मुझे गलत साबित करता है।