2

我有这个代码:

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);
}

这应该将 long long 转换为十六进制或二进制表示,这适用于所有正数,但不适用于负数。

有什么想法可以扩展我的代码以处理签名数字吗?谢谢弗洛里安

编辑:现在我在这里遇到了相反的问题(String -> long long)

4

4 回答 4

4

要转换带符号的值,只需将您的输入转换为 unsigned long long. 除此之外:您不需要建立数字计数,一旦您处理无符号整数类型,只需继续直到它是0. 并确保您至少获得一位数字,即使原始值为0,请使用do ... while循环:

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;

通常更好的解决方案是将最小位数作为参数传递:

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;
}

如果需要,这允许固定格式。

于 2013-09-25T13:15:55.633 回答
2

您不需要预先计算数字:这很昂贵,而且它不适用于负数。

由于您指定要查看二进制补码表示,因此请使用unsigned long longfor yourt来避免否定。

更改循环以继续除以,format直到数字变为零,如下所示:

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());
}
于 2013-09-25T12:37:54.000 回答
1

如果您的数字是负数,您必须执行以下操作:

myNumber = Long.MAXVALUE + myNumber + 1;

之后设置most significant bit.

一个例子:假设你的 Long 没有 64 位,但只有 4 位。

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

所以现在你有了补正数。如果您现在设置最高有效位,您将再次获得负数:

("1"101) = -1

所以我的意思是,你可以计算出你可以描述的数字的正补码,现在你只需要确保你的最重要的十六进制是一个设置了第一个有效位的数字。所以你必须将 8 添加到最重要的十六进制。

例如,您计算4FFA您的正补数,您只需将其更改为CFFA,因为C = 4 + 8.

于 2013-09-25T12:38:35.473 回答
0

对于十六进制变体,如何仅使用std::istringstream和正常流格式?

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

对于二进制文件,这样的事情怎么样:

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;
}
于 2013-09-25T12:36:57.043 回答