3

可能な最大値が与えられた場合、そのような数値を 10 進数形式でテキストとして書き込むために必要なスペースを単純に表現するにはどうすればよいでしょうか?

実際のタスク: Linux で gcc を使用して、プロセス ID ( pid_t) を固定長でログに記録します。std::setw()iomanipulatorで使用するコンパイル時の式があるとよいでしょう。

linux/threads.hヘッダーに、PID_MAXプロセスに割り当てられた最大 pid の値が含まれていることがわかりました。だから持っている

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

これLENGTH(PID_MAX)はコンパイル時の式になりますが、残念ながらこの数値は 16 進数で定義されています。

#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 を 10 進数で表示するのに必要な文字数について、コンパイル時に計算可能な上限を与える必要があります。

于 2009-08-11T13:18:14.767 に答える