在C++中,确定整数有多少位的非常高效的方法是什么?
在C++中,确定整数有多少位的非常高效的方法是什么?
嗯,假设您知道整数的大小,最有效的方法是查找。这比基于对数的较短方法更快。如果您不关心计算“-”,请去掉+1。
#include <climits>
// generic solution
template <class T>
int numDigits(T number)
{
int digits = 0;
if (number < 0) digits = 1; // remove this line if '-' counts as a digit
while (number) {
number /= 10;
digits++;
}
return digits;
}
// partial specialization optimization for 64-bit numbers
template <>
int numDigits(int64_t x) {
if (x == INT64_MIN) return 19 + 1;
if (x < 0) return digits(-x) + 1;
if (x >= 10000000000) {
if (x >= 100000000000000) {
if (x >= 10000000000000000) {
if (x >= 100000000000000000) {
if (x >= 1000000000000000000)
return 19;
return 18;
}
return 17;
}
if (x >= 1000000000000000)
return 16;
return 15;
}
if (x >= 1000000000000) {
if (x >= 10000000000000)
return 14;
return 13;
}
if (x >= 100000000000)
return 12;
return 11;
}
if (x >= 100000) {
if (x >= 10000000) {
if (x >= 100000000) {
if (x >= 1000000000)
return 10;
return 9;
}
return 8;
}
if (x >= 1000000)
return 7;
return 6;
}
if (x >= 100) {
if (x >= 1000) {
if (x >= 10000)
return 5;
return 4;
}
return 3;
}
if (x >= 10)
return 2;
return 1;
}
// partial specialization optimization for 32-bit numbers
template<>
int numDigits(int32_t x)
{
if (x == INT32_MIN) return 10 + 1;
if (x < 0) return numDigits(-x) + 1;
if (x >= 10000) {
if (x >= 10000000) {
if (x >= 100000000) {
if (x >= 1000000000)
return 10;
return 9;
}
return 8;
}
if (x >= 100000) {
if (x >= 1000000)
return 7;
return 6;
}
return 5;
}
if (x >= 100) {
if (x >= 1000)
return 4;
return 3;
}
if (x >= 10)
return 2;
return 1;
}
// partial-specialization optimization for 8-bit numbers
template <>
int numDigits(char n)
{
// if you have the time, replace this with a static initialization to avoid
// the initial overhead & unnecessary branch
static char x[256] = {0};
if (x[0] == 0) {
for (char c = 1; c != 0; c++)
x[c] = numDigits((int32_t)c);
x[0] = 1;
}
return x[n];
}
最简单的方法是这样做:
unsigned GetNumberOfDigits (unsigned i)
{
return i > 0 ? (int) log10 ((double) i) + 1 : 1;
}
log10在<cmath>
或<math.h>
中定义。你需要对此进行分析以确定它是否比此处发布的其他任何方法都更快。我不确定它在浮点精度方面有多强大。此外,该参数是无符号的,因为负值和对数并不真正混合。
int NumDigits(int x)
{
x = abs(x);
return (x < 10 ? 1 :
(x < 100 ? 2 :
(x < 1000 ? 3 :
(x < 10000 ? 4 :
(x < 100000 ? 5 :
(x < 1000000 ? 6 :
(x < 10000000 ? 7 :
(x < 100000000 ? 8 :
(x < 1000000000 ? 9 :
10)))))))));
}
x = abs(x)
在这里起到了额外的作用。 - VisioN1
。由于被测试的函数对负数没有做同样的事情,我删除了负数并在两个函数中使用了类型 std::uint_fast32_t
。 - Ted Lyngmoint digits = 0; while (number != 0) { number /= 10; digits++; }
注: "0" 将没有任何数字!如果你需要它显示一个数字,可以使用以下方法:int digits = 0; do { number /= 10; digits++; } while (number != 0);
(感谢Kevin Fegan)
最终,使用性能分析器来确定这里所有答案中哪个在您的计算机上更快...
将其转换为字符串,然后使用内置函数。
unsigned int i;
cout<< to_string(i).length()<<endl;
恶作剧:这是最高效的方法(数字的数量在编译时计算):
template <unsigned long long N, size_t base=10>
struct numberlength
{
enum { value = 1 + numberlength<N/base, base>::value };
};
template <size_t base>
struct numberlength<0, base>
{
enum { value = 0 };
};
这可能有助于确定格式化,输入元素等所需的数字字段宽度。
请参考《位操作技巧》,里面有一个更简短的答案,如果您的输入数据是正常分布的话,它还可以更快地找到答案,因为它首先检查大的常量。 (v >= 1000000000)
可以捕获 76% 的值,所以首先检查这个条件平均会更快。
int x = 1000;
int numberOfDigits = x ? static_cast<int>(log10(abs(x))) + 1 : 1;
之前的帖子建议使用除以10的循环。由于现代计算机上的乘法速度更快,我建议改用以下代码:
int digits = 1, pten=10; while ( pten <= number ) { digits++; pten*=10; }
ppc架构具有位计数指令。使用它,您可以在单个指令中确定正整数的以2为底的对数。例如,32位将是:
#define log_2_32_ppc(x) (31-__cntlzw(x))
如果您可以处理大量数据的小误差,您可以使用另外几个指令将其转换为以10为底的对数:
#define log_10_estimate_32_ppc(x) (9-(((__cntlzw(x)*1233)+1545)>>12))
这是平台特定的,略有不准确,但也不涉及分支、除法或转换为浮点数。一切取决于您的需求。
我只知道ppc指令,但其他架构应该有类似的指令。