3

给定最大可能值,如何简单地表示以十进制形式将此类数字写入文本所需的空间?

pid_t真正的任务:在 Linux 上使用 gcc 以固定长度记录进程 id ( )。在std::setw()iomanipulator 中使用编译时表达式会很好。

我发现linux/threads.h标头包含一个PID_MAX分配给进程的最大 pid 值。所以有

#define LENGTH(t) sizeof(#t)-1

LENGTH(PID_MAX)将是一个编译时表达式,但不幸的是这个数字是在十六进制中定义的:

#define PID_MAX 0x8000

我目前最好的解决方案有点奇怪

static_cast<int>( ::floor( ::log(PID_MAX)/::log(10) + 1 ) );

但这是计算运行时并使用math.h中的函数

4

2 回答 2

14

您可以通过一些模板元编程来做到这一点:

//NunLength_interal does the actual calculation. 
template <unsigned num>
struct NumLength_internal
{ enum { value = 1 + NumLength_internal<num/10>::value }; };

template <>
struct NumLength_internal<0>
{ enum { value = 0 }; };

//NumLength is a wrapper to handle zero. For zero we want to return
//a length of one as a special case.
template <unsigned num>
struct NumLength
{ enum { value = NumLength_internal<num>::value };};

template <>
struct NumLength<0>
{ enum { value = 1 }; };

这现在应该适用于任何事情。例如:

cout << NumLength<0>::value      << endl; // writes: 1
cout << NumLength<5>::value      << endl; // writes: 1
cout << NumLength<10>::value     << endl; // writes: 2
cout << NumLength<123>::value    << endl; // writes: 3
cout << NumLength<0x8000>::value << endl; // writes: 5

这都是在编译时处理的。

编辑:我添加了另一层来处理传入的数字为零的情况。

于 2009-08-11T13:37:18.313 回答
2

我认为如果不调用对数就不能完全得到它,但你可以获得一个上限:

CHAR_BIT * sizeof(PID_MAX)将为您提供表示 PID_MAX 所需的位数的上限。然后,您可以预先计算 log(10) = 3.32 并向下舍入到 3。忘记下限,因为无论如何整数除法都会像那样截断。所以

#define LENGTH(t) (((CHAR_BIT * sizeof(t)) / 3) + 1)

应该给你一个编译时可计算的上限,以十进制显示 t 所需的字符数。

于 2009-08-11T13:18:14.767 回答