简体   繁体   中英

Convert long long into Hex and Binary in c++

I have this code:

char digits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
    'C', 'D', 'E', 'F' };
string toFormatFromDecimal(long long t, Format format) {
    int digitCount = ceil(log(t) / log((int) format));
    string hex = "";
    for (int i = 0; i < digitCount; i++) {
        hex += digits[(int) (t%format)];
        t = t/format;
    }        
    return string(hex.rbegin(), hex.rend());
}
string toHexFromDecimal(long long t) {
        return "0x" + toFormatFromDecimal(t, HEX);
}

string toBinFromDecimal(long long t) {
    return toFormatFromDecimal(t, BIN);
}

This should convert long long into hex- or binary-representation, which works well for all possitive numbers, but doesn't with negative numbers.

Any ideas how I can extend my code to handle signed numbers as well? Thanks Florian

EDIT: Now I have a similar problem for the opposite (String -> long long) here

To convert the signed values, just convert your input to unsigned long long . Other than that: you don't need to establish a digit count, once you're dealing with an unsigned integral type, just continue until it is 0 . And to make sure you get at least one digit, even if the original value was 0 , use a do ... while loop:

std::string results;
unsigned long long tmp = t;
do
{
    results += digits[ tmp % format ];
    tmp /= format;
} while ( tmp != 0 );
std::reverse( results.begin(), results.end() );
return results;

An often better solution is to pass the minimum number of digits in as an argument:

std::string
toString( unsigned long long value, int base, int minSize = 1 )
{
    static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    assert( base >= 2 && base <= 36 );
    std::string results;
    while ( value != 0 || results.size() < minSize ) {
        results += digits[ value % base ];
        value /= base;
    }
    std::reverse( results.begin(), results.end() );
    return results;
}

This allows fixed format, if desired.

You do not need to count digits upfront: it's costly, and it does not work for negative numbers.

Since you specified that you would like to see a two's complement representation, use unsigned long long for your t to avoid negatives.

Change your loop to continue dividing by format until the number gets to zero, like this:

string toFormatFromDecimal(unsigned long long t, Format format) {
    string res = "";
    do {
        res += digits[(int) (t%format)];
        t = t/format;
    } while (t);
    return string(res.rbegin(), res.rend());
}

If your number is negative you must do:

myNumber = Long.MAXVALUE + myNumber + 1;

After that set the most significant bit .

An example: Assuming, your Long does not have 64 bit but only 4.

You have the number -3 (1101)
number = 7 + (-3) + 1 = 5 (0101)

So now you have the complement positive number. If you now set the most significant bit you have your negative number again:

("1"101) = -1

So what I mean is, you could calculate the positive complement of your number that you could describe like you did and now you just have to make sure, that your most significant hex is a number with the first significant bit set.So you have to add 8 to the most significant hex.

Eg you calculate 4FFA for your positive complement number you just have to change it to CFFA , because C = 4 + 8 .

For the hexadecimal variant, how about just use std::istringstream and normal stream formatting?

Like

std::string toHexFromDecimal(long long t) {
    std::istringstream is;
    is << std::hex << t;
    return t.str();
}

For binary, how about something like this:

std::string toBinFromDecimal(long long t) {
    std::string s;

    for (int bit = sizeof(t) * 8 - 1; bit >= 0; --bit) {
        s += '0' + (t >> bit) & 1;
    }

    return s;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM