计算作为文本写入的数字长度的最简单/最优雅的方法是什么?

时间:2009-08-11 13:10:24

标签: c++ fixed-length-record

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

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

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

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

LENGTH(PID_MAX)将是一个编译时表达式,但不幸的是这个数字是以hexa定义的:

#define PID_MAX 0x8000

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

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

但这是计算运行时并使用 math.h

中的函数

2 个答案:

答案 0 :(得分: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

这都是在编译时处理的。

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

答案 1 :(得分:2)

我不认为你可以在没有调用对数的情况下完全得到它,但你可以得到一个上限:

CHAR_BIT * sizeof(PID_MAX)将给出表示PID_MAX所需位数的上限。然后你可以预先计算log(10)= 3.32并向下舍入到3.忘掉楼层,因为整数除法无论如何都会截断。所以

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

应该为您提供以十进制显示t所需的字符数的编译时可计算上限。