我正在编写代码,该代码从用户那里获取一个数字并以字母形式作为字符串打印回来。我想知道,在性能方面,有 if 语句,比如
if (n < 100) {
// code for 2-digit numbers
} else if (n < 1000) {
// code for 3-digit numbers
} // etc..
或将数字放入字符串中并获取其长度,然后将其作为字符串处理。
代码是用 C++ 编写的。
我正在编写代码,该代码从用户那里获取一个数字并以字母形式作为字符串打印回来。我想知道,在性能方面,有 if 语句,比如
if (n < 100) {
// code for 2-digit numbers
} else if (n < 1000) {
// code for 3-digit numbers
} // etc..
或将数字放入字符串中并获取其长度,然后将其作为字符串处理。
代码是用 C++ 编写的。
当然if-else
会更快。
要比较两个数字,您只需按位比较它们(有不同的方法可以做到,但这是一个非常快的操作)。
要获得字符串的长度,您需要制作字符串,将数据放入其中并以某种方式计算长度(也可以有不同的方法,最简单的是计算所有符号)。当然,这需要更多的时间。
在一个简单的例子中,虽然你不会注意到任何区别。人们常常关心这些事情(无意冒犯),这常常让我感到惊讶。如果代码将在0.003
几秒钟内而不是0.001
几秒钟内执行,这对您没有任何影响......只有在您知道这个确切位置是您的应用程序的瓶颈并且确定您可以将性能提高相当多。
答案很好,但请考虑一下相对时间。
即使通过你能想到的最慢的方法,程序也可以在几分之一秒内完成,比如 100 微秒。
将其与您可以想象的最快的用户进行平衡,谁可以在 500 毫秒内输入数字,谁可以在另外 500 毫秒内读取输出,然后再执行下一步操作。
好的,这台机器在 1000 毫秒内基本上什么都不做,而在中间它必须疯狂地运行 100 微秒,因为毕竟我们不希望用户认为程序很慢 ;-)
在您测量并且这确实是一个瓶颈之前,不要担心性能。
也就是说,以下内容应该更快(为了便于阅读,假设您使用的类型介于 0 和 99999999 之间):
if (n < 10000) {
// code for less or equal to 4 digits
if (n < 100)
{
//code for less or equal to 2 digits
if (n < 10)
return 1;
else
return 2;
}
else
{
//code for over 2 digits, but under or equal to 4
if (n>=1000)
return 4;
else
return 3;
}
} else {
//similar
} // etc..
基本上,它是二分搜索的一种变体。在最坏的情况下,这将O(log(n))
与O(n)
-n
作为最大位数相反。
string
变体会更慢:
std::stringstream ss; // allocation, initialization ...
ss << 4711; // parsing, setting internal flags, ...
std::string str = ss.str(); // allocations, array copies ...
// cleaning up (compiler does it for you) ...
str.~string();
ss.~stringstream(); // destruction ...
表明有更多的...
事情发生。
一个紧凑的(适用于缓存)循环(适用于分支预测)可能是您想要的:
int num_digits (int value, int base=10) {
int num = 0;
while (value) {
value /= base;
++num;
}
return num;
}
int num_zeros (int value, int base=10) {
return num_decimal_digits(value, base) - 1;
}
根据情况,因为它对缓存和预测友好,所以这可能比基于关系运算符的解决方案更快。
模板化变体使编译器能够为您的部门进行一些微优化:
template <int base=10>
int num_digits (int value) {
int num = 0;
while (value) {
value /= base;
++num;
}
return num;
}