मेरे पास इस तरह का एक कार्य है: उपयोगकर्ता हेक्साडेसिमल में संख्या N1 (str1) और N2 (str2) दर्ज करता है। प्रोग्राम को संख्याओं को हेक्साडेसिमल से 2 ^ 16 के सिस्टम में बदलना होगा और 2^16 सिस्टम में संख्याओं N1 और N2 के योग को गिनना होगा, फिर परिणाम को हेक्साडेसिमल सिस्टम में ट्रांसलेट करना होगा।

मेरे पास ऐसा विचार था: पहले हेक्साडेसिमल से दशमलव में कनवर्ट करें (मैं यह कर सकता हूं)। फिर संख्या N1dec(dec11) (या N2dec(dec22)) के आधार 2 ^ 16 का लघुगणक मोडुलो 2 ^ 16 लें और शेष को संबंधित सरणियों में लिखें। यहीं से मेरी परेशानी शुरू हुई। दशमलव से 2^16 प्रणाली में मेरा रूपांतरण काम नहीं करता है। आशा है कि आप मदद कर सकते हैं।

#include <iostream> 
using namespace std;

int main()
{
//HEX to decimal
const char* const str1 = "101D0";//7A120 = 500000; 101D0 = 66000;   //1F4 = 500=dec1=N1
cout << "Hello!\nFirst number in HEX system is " << str1 << endl;
istringstream is(str1);
int dec1;
is >> hex >> dec1;
if (!is && !is.eof()) throw "dammit!";
cout << "First number in decimal system: " << dec1 << endl;
const char* const str2 = "1567";//5479=dec2=num2
cout << "Second number in HEX system is " << str2 << endl;
istringstream iss(str2);
int dec2;
iss >> hex >> dec2;
if (!iss && !iss.eof()) throw "dammit!";
cout << "Second number in decimal system: " << dec2 << endl;
//

//Decimal to 2^16 system
int dec11 = dec1;//because dec11 will be = 0
int dec22 = dec2;//because dec22 will be = 0

int k = 1 << 16;
cout << "2^16 = " << k << endl;
int intPART1 = log(dec11) / log(k);
cout << "Int part of log2^16 (" << dec11 << ") is " << intPART1 << endl << "So num1 in 2^16 system will look like ";

int *n1 = new int[intPART1 + 1];
for (int i = 0; i <= intPART1; i++)
{
    if (i != 0)
    {
        n1[i] = dec11 % k*(1<<16-1);
        dec11 = dec11 / k;
    }
    else
    {
        n1[i] = dec11 % k;
        dec11 = dec11 / k;
    }
}
for (int i = intPART1; i >= 0; i--)
{
    cout << n1[i] << "   ";
}
cout << endl;
int intPART2 = log(dec22) / log(k);
cout << "Int part of log2^16 (" << dec22 << ") is " << intPART2 << endl << "So num2 in 2^16 system will look like ";

int *n2 = new int[intPART2 + 1];
for (int i = 0; i <= intPART2; i++)
{
    if (i != 0)
    {
        n2[i] = dec22 % k*(1 << 16 - 1);
        dec22 = dec22 / k;
    }
    else
    {
        n2[i] = dec22 % k;
        dec22 = dec22 / k;
    }
}

for (int i = intPART2; i >= 0; i--)
{
    cout << n2[i] << "   ";
}
cout << endl;
1
Laura 2 अक्टूबर 2019, 01:17
इसका मेरी टिप्पणी से कोई लेना-देना नहीं है। std::stoi एक स्ट्रिंग को एक इंट में कनवर्ट करता है और आप कर सकते हैं उस स्ट्रिंग का आधार निर्दिष्ट करें।
 – 
Timo
2 अक्टूबर 2019, 01:22
1
2^16 के सिस्टम से आपका मतलब आधार 65536 की संख्या से है?
 – 
Timo
2 अक्टूबर 2019, 01:25
हाँ, आधार संख्या 65536
 – 
Laura
2 अक्टूबर 2019, 01:34
1
"आधार 65536" - एक अंक में 65535 मान हो सकते हैं ?? आप 1000000 को दो अंकों के रूप में लिखेंगे: 15 दशमलव अंक और 16960 इकाई अंक?
 – 
KamilCuk
2 अक्टूबर 2019, 02:20
आप जो प्रयास कर रहे हैं, उसकी तुलना में रूपांतरण अधिक सीधा होना चाहिए। प्रत्येक आधार-2^16 अंक को ठीक 4 आधार-16 अंकों द्वारा दर्शाया जाता है।
 – 
paddy
2 अक्टूबर 2019, 02:25

2 जवाब

सबसे बढ़िया उत्तर

चूंकि हेक्साडेसिमल मान आधार 16 के हैं, मान लें कि 16^1 और आधार 2^16 को 16^4 में पुनर्गणना किया जा सकता है, हम पहले से ही देख सकते हैं कि आपका लक्ष्य आधार आपके स्रोत आधार का गुणक है। यह गणना को बहुत आसान और सीधे आगे बनाता है। हमें बस इतना करना है कि थोड़ा सा बदलाव करना है।

int hexToInt(char c)
{
    if (c >= 'a')
        return c - 'a' + 10;
    if (c >= 'A')
        return c - 'A' + 10;
    return c - '0';
}

// Converts hex to base 2^16. vector[0] holds the MSB.
std::vector<unsigned short> toBase0x10000(std::string const& hex)
{
    std::size_t bufSize = hex.size() / 4 + (hex.size() % 4 > 0);
    std::vector<unsigned short> number(bufSize);

    int shift = 0;
    int value = 0;
    std::size_t numIndex = number.size();

    for (int i = hex.size() - 1; i >= 0; i--)
    {
        value |= hexToInt(hex[i]) << shift;
        shift += 4;

        if (shift == 16)
        {            
            number[--numIndex] = static_cast<unsigned short>(value);
            shift = 0;
            value = 0;
        }
    }

    if (value != 0)
        number[--numIndex] = static_cast<unsigned short>(value);

    return number;
}

std::string fromBase0x10000(std::vector<unsigned short> const& num)
{
    std::stringstream ss;
    for (auto&& digit : num)
        ss << std::hex << digit;
    return ss.str();
}

toBase0x10000 एक std::vector<unsigned short> देता है, इसलिए वेक्टर में प्रत्येक तत्व आपके आधार 2^16 संख्या के एक अंक का प्रतिनिधित्व करता है (क्योंकि unsigned short उस मान श्रेणी को सटीक रूप से धारण कर सकता है)।

एक साइड इफेक्ट के रूप में यह कार्यान्वयन किसी भी सटीक संख्या का समर्थन करता है, इसलिए आप int या long जैसे संख्यात्मक प्रकारों की मान सीमा तक सीमित नहीं हैं।

यहां एक पूरा उदाहरण है।

2
Timo 2 अक्टूबर 2019, 02:31
आपने std::size_t bufSize = hex.size() / 4 + (hex.size()% 4 > 0) क्यों लिखा; एसटीडी के बजाय :: size_t bufSize = hex.size (); ?
 – 
Laura
2 अक्टूबर 2019, 22:09
और यह कैसे काम करता है (hex.size ()% 4> 0)? क्या यह वामपंथ की शून्य से तुलना नहीं है?
 – 
Laura
2 अक्टूबर 2019, 22:17
"ए" और "ए" के बीच क्या अंतर है और हमें सी - 'ए' + 10 वापस करने की आवश्यकता क्यों है? अगर मेरे पास संख्या 1F4 है तो 4 - 'ए' = -13, -6 नहीं, जब हेक्साडेसिमल सिस्टम 'ए' में यह दशमलव में '10' है। मुझे एक धारणा है कि यह ASCII तालिकाओं के कारण है, लेकिन मुझे समझ में नहीं आता कि कैसे। कृपया मुझे समझायें।
 – 
Laura
2 अक्टूबर 2019, 23:09
hex.size() / 4 भाग इसलिए है क्योंकि वेक्टर unsigned short प्रकार का है जो कि 16 बिट का है। एक हेक्स वर्ण (0-एफ) बिल्कुल 4 बिट्स में फिट हो सकता है, इसलिए उन दो प्रकारों के बीच 1/4 अनुपात होता है। हालाँकि 1/4 अनुपात में यह भी समस्या है कि यह हमेशा एक गोल संख्या नहीं देता है। भूतपूर्व। "123456789" में 9 वर्ण हैं। यदि हम उसे 4 से भाग दें तो हमें 2.25 प्राप्त होता है जो पूर्णांक अंकगणित 2 में कट जाएगा। यहीं पर + (hex.size() % 4 > 0) चलन में आता है। यह जाँचता है कि क्या स्ट्रिंग का आकार 4 से विभाज्य है और यदि नहीं, तो 1 को bufSize में जोड़ता है (अन्यथा व्यंजक 0 है)।
 – 
Timo
2 अक्टूबर 2019, 23:42
(hex.size() % 4 > 0) एक बूलियन व्यंजक है। और अंकगणित में true का अनुवाद 1 और false से 0 होता है।
 – 
Timo
2 अक्टूबर 2019, 23:43

चूंकि यह सीखने के अभ्यास की तरह दिखता है जिसे आप स्वयं हल करना चाहते हैं, यहां दो संकेत दिए गए हैं।

एक हेक्स अंक चार बिट्स का प्रतिनिधित्व करता है, इसलिए प्रत्येक आधार -65,536 अंक में चार हेक्स अंक होते हैं। इसलिए आप अंकों को चार के समूहों में पढ़ सकते हैं, जिसमें दशमलव को या दशमलव में बदलने की आवश्यकता नहीं है। चार दशमलव अंकों को डीकोड करने के लिए आपने जो एल्गोरिदम सीखा है, वह हेक्स के लिए काम करेगा, गुणन को छोड़कर और भी अधिक कुशल होगा क्योंकि संकलक उन्हें बाएं-शिफ्ट निर्देशों में अनुकूलित करेगा।

आपको इस अंकगणित के लिए uint16_t से <stdint.h> प्रकार का उपयोग करना चाहिए, क्योंकि यह बिल्कुल सही आकार और अहस्ताक्षरित है। अहस्ताक्षरित अंकगणितीय अतिप्रवाह को चारों ओर लपेटने के रूप में परिभाषित किया गया है, जो आप चाहते हैं। हस्ताक्षरित अतिप्रवाह अपरिभाषित व्यवहार है। (या यदि आप चाहें तो #include <cstdint> के बाद using std::uint16_t;।)

किसी भी आधार b में अंक जोड़ने के लिए, modulo b के अंकों का योग लें। यह तब और भी आसान हो जाएगा जब b 2 की शक्ति हो, क्योंकि x86 और कई अन्य CPU में 16-बिट अहस्ताक्षरित ऐड निर्देश होता है जो हार्डवेयर में ऐसा करता है, और किसी भी मशीन पर जो नहीं करता है, संकलक इसे बिटमास्क & 0xFFFFU में अनुकूलित कर सकता है।

दोनों ही मामलों में, यदि आप चाहें, तो * और % के बजाय << और & का उपयोग करके हाथ से द्विआधारी अनुकूलन लिख सकते हैं। यदि आप अहस्ताक्षरित गणित के बजाय हस्ताक्षरित का उपयोग करते हैं, तो यह उत्पन्न कोड में थोड़ा सुधार कर सकता है। हालांकि, कोई भी आधुनिक कंपाइलर आपके लिए इस तरह का माइक्रो-ऑप्टिमाइज़ेशन करने के लिए पर्याप्त स्मार्ट है। बेहतर होगा कि आप समय से पहले अनुकूलन न करें, और ऐसा कोड लिखें जो पढ़ने और समझने में आसान हो।

0
Davislor 2 अक्टूबर 2019, 02:49