这里有几个不同的C++实现*,它们都是一个名为digits()
的函数,该函数以size_t
为参数并返回其数字的数量。如果您的数字是负数,则必须将其绝对值传递给函数,以便它正常工作:
While循环
int digits(size_t i)
{
int count = 1;
while (i /= 10) {
count++;
}
return count;
}
穷举优化技术
int digits(size_t i) {
if (i > 9999999999999999999ull) return 20;
if (i > 999999999999999999ull) return 19;
if (i > 99999999999999999ull) return 18;
if (i > 9999999999999999ull) return 17;
if (i > 999999999999999ull) return 16;
if (i > 99999999999999ull) return 15;
if (i > 9999999999999ull) return 14;
if (i > 999999999999ull) return 13;
if (i > 99999999999ull) return 12;
if (i > 9999999999ull) return 11;
if (i > 999999999ull) return 10;
if (i > 99999999ull) return 9;
if (i > 9999999ull) return 8;
if (i > 999999ull) return 7;
if (i > 99999ull) return 6;
if (i > 9999ull) return 5;
if (i > 999ull) return 4;
if (i > 99ull) return 3;
if (i > 9ull) return 2;
return 1;
}
递归的方式
int digits(size_t i) { return i < 10 ? 1 : 1 + digits(i / 10); }
使用 snprintf()
作为字符计数器
⚠ 需要 #include <stdio.h>
,与其他解决方案相比可能会产生显著的性能损失。这种方法利用了 snprintf()
在缓冲区满时丢弃的字符数量。因此,通过正确的参数和格式说明符,我们可以强制 snprintf()
给出任何 size_t
的数字位数。
int digits(size_t i) { return snprintf (NULL, 0, "%llu", i); }
对数方法
⚠ 需要 #include <cmath>
,对于超过14位数字的无符号整数不可靠。
int digits(size_t i) { return !i? 1 : 1 + log10(i); }
驱动程序
您可以使用此程序测试任何取size_t
为参数并返回其数字个数的函数。只需替换以下代码中digits()
函数的定义:
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <chrono>
using std::cout;
using namespace std::chrono;
int digits(size_t i)
{
int count = 1;
while (i /= 10) {
count++;
}
return count;
}
int main ()
{
const int max = digits(~0ull);
size_t i = 0, d;
do {
auto t0 = high_resolution_clock::now();
d = digits(i);
auto t1 = high_resolution_clock::now();
duration<double, std::nano> te = t1 - t0;
cout << i << " has " << d << " digits (" << te.count() << " ns).\n";
i = d < max ? (!i ? 9 : 10 * i - 1) : ~0ull;
t0 = high_resolution_clock::now();
d = digits(i);
t1 = high_resolution_clock::now();
te = t1 - t0;
cout << i << " has " << d << " digits (" << te.count() << " ns).\n";
} while (++i);
}
* 所有内容都是在 Windows 10 (64位) 的机器上使用 Visual Studio Code 中的 GCC 12.2.0 进行测试的。
std::string
?你可以直接使用strlen(buffer_length)
。你也不需要\n
,因此也不需要-1
。 - leemessnprintf()
技巧,例如int needed = snprintf (NULL, 0, "%d", 234567545);
参见man 3 printf 中 "RETURN VALUE" 第二段的第二句话。 - David C. Rankin