我有一个正整数3只基本表示:
- 十进制,在无符号长变量(例如unsigned long int类型NumDec = 200)。
- 十六进制,在字符串变量(例如字符串NumHex =“C8”)
- 二进制,在字符串变量(例如字符串NumBin =“11001000”)
我希望能够在所有3个表示数字之间转换的最有效的方式。 即实现以下6个功能:
unsigned long int Binary2Dec(const string & Bin) {}
unsigned long int Hex2Dec(const string & Hex) {}
string Dec2Hex(unsigned long int Dec) {}
string Binary2Hex(const string & Bin) {}
string Dec2Binary(unsigned long int Dec) {}
string Hex2Binary(const string & Hex) {}
什么是他们每个人的最有效的方法? 我可以使用C和C ++,但是不能增加。
编辑:由“效率”我的意思是时间效率:执行时间最短。
Answer 1:
正如其他人所指出的那样,我会开始sscanf()
printf()
和/或strtoul()
他们是对于大多数应用足够快,他们不太可能有错误。 我会说,但是,这些功能比你想象的更通用的,因为他们必须处理非ASCII字符集,在任何基地等为代表的数字。 对于某些领域有可能击败库函数。
所以,衡量第一,如果这些转换的性能确实是一个问题,那么:
1)在一些应用/域特定号码出现非常频繁,例如零,100,200,19.95,可以是很常见的,是有意义的优化功能这样的数字转换和一群如果()语句,然后退回到通用库函数。 2)如果中最常见的100个号码使用表查找,然后依傍的库函数。 请记住,大表可能不适合你的缓存,并且可能需要共享库多个间接性,所以仔细测量这些事情,以确保您不会降低性能。
您可能还需要看看升压lexical_cast的功能,但在我的经验,后者相对比较好老的C函数。
艰难许多人说,这是值得重复一遍又一遍:除非你有证据证明他们是个问题不优化这些转换。 如果你不优化,衡量你的新的实现,以确保它是更快,确保你有一吨的单元测试你自己的版本,因为你会引入错误:-(
Answer 2:
我只想用建议的sprintf和sscanf的 。
另外,如果你有兴趣它是如何实现的,你可以看看的源代码进行的glibc,GNU C库 。
Answer 3:
这些例程为什么要这样时间效率? 那种要求的总是让我惊叹。 你确定明显的转换方法,如与strtol()的速度太慢,或者你可以做的更好? 系统功能通常是非常有效的。 他们有时慢,以支持通用和错误检查功能,但你需要考虑如何处理错误的事情。 如果bin
的说法比“0”和“1”其它字符,然后呢? 中止? 大规模传播的错误?
你为什么要使用“DEC”代表内部表示? 十二月,十六进制和Bin应该用来指代字符串表示。 有关于什么十进制unsigned long
。 你处理字符串显示十进制数? 如果没有,你在这里混淆人会混淆等等。
二进制和十六进制的文本格式之间的转换可以快速,高效地进行,并查找表,但任何涉及十进制文本格式将更加复杂。
Answer 4:
这取决于你正在优化什么,你是什么意思“高效”是什么意思? 它是重要的转换要快,使用较少的内存,小程序员的时间,更少的WTFs从其他程序员阅读代码,还是什么?
对于可读性和易于实施的,你至少应该实现这两个Dec2Hex()
和Dec2Binary()
被调用刚刚strotul()
这使得他们变成单行,这是至少一些字的上述解释的非常有效的。
Answer 5:
听起来很像一门功课的问题,但到底什么...
简短的回答是从长整型转换到你的字符串使用两个查找表。 每个表应该有256项。 一个映射到十六进制字符串字节:> “00000000”,1 - - > “00000001” 0:0 - - > “00”,1> “01” 等。其它的比特串中的字节映射。
然后在你的长期每个字节诠释你只需要查找正确的字符串,以及将它们连接起来。
要从字符串转换回长,你可以简单地通过16或2的适当功率的每个字符的数字值乘以和总结的结果十六进制字符串和位字符串转换回十进制数。
编辑:您还可以使用向后转换相同的查找表做二进制搜索找到合适的字符串。 这将需要数(256)=你的琴弦8个比较。 不幸的是我没有时间做了分析是否比较字符串会比相乘并添加整数快得多。
Answer 6:
让我们想想任务过半的时刻 - 从字符串化的基数n转换为unsigned long,其中n为2的幂(基数为2二进制和十六进制基数为16)。
如果输入是理智的,那么这项工作无非就是一个比较,一个subract,移位和或每个数字。 如果输入不理智的,好了,这就是它变得丑陋,不是吗? 在做转换超快并不难。 做的很好在所有情况下是一个挑战。
因此,让我们假设你的输入是理智的,那么转换的心脏是这样的:
unsigned long PowerOfTwoFromString(char *input, int shift)
{
unsigned long val = 0;
char upperLimit = 'a' + (1 << shift)
while (*input) {
char c = tolower(*input++);
unsigned long digit = (c > 'a' && c < upperLimit) ? c - 'a' + 10 : c - '0';
val = (val << shift) | digit;
}
return val;
}
#define UlongFromBinaryString(str) PowerOfTwoFromString(str, 1)
#define UlongFromHexString(str) PowerOfTwoFromString(str, 4)
见多么容易那是什么? 它会失败在非理智的投入。 你的大部分工作是要进入使你的输入理智,而不是性能。
现在,这个代码利用两个换挡的力量。 可以很容易地扩展到基座4,基座8,底座32等,这将不会在2个碱基的非动力工作。 对于这些,你的数学必须改变。 你得到
val = (val * base) + digit
这是概念上的这组相同的操作。 由基的乘法将是等同于移位。 所以,我会为可能使用完全通用的例程。 和消毒的代码,而消毒的投入。 而在这一点上,strtoul将可能是你最好的选择。 这里有一个链接一个版本 strtoul将。 几乎所有的工作是处理边界条件 - 这应该线索你在哪里,你的精力应该集中:正确的,有弹性的代码。 使用位移位储蓄会相比,说,不是崩溃坏输入储蓄是微乎其微。
Answer 7:
为什么不直接使用宏也采取格式作为输入。 如果您在C最少。
#define TO_STRING( string, format, data) \
sprintf( string, "##format##", data)
// Int
TO_STRING(buf,%d,i);
// Hex ( Two char representation )
TO_STRING(buf,%02x,i);
// Binary
TO_STRING(buf,%b,i);
或者你也可以直接用sprintf:或者你可以有多个macroes。
#define INT_STRING( buf, data) \
sprintf( buf, "%d", data)
#define HEX_STRING( buf, data) \
sprintf( buf, "%x", data)
#define BIN_TO_STRING( buf, data) \
sprintf( buf, "%b", data)
BIN_TO_STRING( loc_buf, my_bin );
文章来源: Efficiently convert between Hex, Binary, and Decimal in C/C++