0

char data[len]バイナリファイルから読み取られた解凍済みデータからデータが取り込まれています。dataはこれらのタイプのみであることがわかっています: char, uchar, short, ushort, int, uint, float, double( ) を表すのに必要な正確なビット数を知っていelesize = {8, 16, 32, 64}ます。

max()データリストをトラバースして、たとえば、min()特定の数値の出現回数を見つけたいだけです。メモリ空間の問題のために別の配列を作成せずにこれを行いたいです。

私は次のことを思いつきましたが、たとえば遅いですlen == 34560000

だから、誰かが「ワンライナー」またはこれを行うためのより効率的な方法(CまたはC ++のいずれか)を持っているかどうか疑問に思っていました。

char data[len];
double mymax = -std::numeric_limits<double>::max()
for (size_t i=0; i<len; i += elesize)
{
    double x;
    char *r = data+i;
    if (elementtype == "char")
        x = static_cast<double>(*r);
    else if (elementtype == "uchar")
        x = static_cast<double>(*((unsigned char *)r));
    else if (elementtype == "short")
        x = static_cast<double>(*((int16_t *)r));
    else if (elementtype == "ushort")
        x = static_cast<double>(*((uint16_t *)r));
    else if (elementtype == "int")
        x = static_cast<double>(*((int32_t *)r));
    else if (elementtype == "uint")
        x = static_cast<double>(*((uint32_t *)r));
    else if (elementtype == "float")
        x = static_cast<double>(*((float *)r));
    else if (elementtype == "double")
        x = *((double *)r);
    if (x > mymax)
        mymax = x;
}
4

4 に答える 4

1

テンプレートはうまくいくはずです:

#include <algorithm>

template <typename T>
T read_and_advance(const unsigned char * & p)
{
  T x;
  unsigned char * const px = reinterpret_cast<unsigned char *>(&x);

  std::copy(p, p + sizeof(T), px);
  P += sizeof(T);

  return x;
}

使用法:

const unsigned char * p = the_data;
unsigned int max = 0;

while (p != the_data + data_length)
{
  max = std::max(max, read_and_advance<unsigned int>(p));
}

これをスクラップします。もともと質問はC向けだと思っていました。

マクロは次のとおりです。

#define READ_TYPE(T, buf, res) do { memcpy(&res, buf, sizeof(T)); buf += sizeof(T); } while (false)

使用法:

int max = 0;
unsigned char * p = data;

while (true)
{
  unsigned int res;
  READ_TYPE(unsigned int, p, res);
  if (res > max) max = res;
}

ただし、 typeの指定を実際に回避することはできません。C++ では、これをもう少しエレガントに行うことができます。

または、すべてを 1 つにラップすることもできます。

#define READ_TYPE_AND_MAX(T, buf, max)  \
  do { T x; memcpy(&x, buf, sizeof(T)); \
       buf += sizeof(T);                \
       if (max < x) max = x;            \
  } while (false)

// Usage:
unsigned int max = 0;
unsigned char * p = data;
while (true) { READ_TYPE_AND_MAX(unsigned int, p, max); }

于 2011-11-17T20:06:53.290 に答える
0

条件付きコードをループの外に置くと、ループが高速に実行されます。次のようなことを試してください:

char data[len];
double mymax = -std::numeric_limits<double>::max()
double x;
if (elementtype == "char") {
  for (size_t i=0; i<len; i += elesize) {
    char *r = data+i;
    x = static_cast<double>(*r);
    if (x > mymax)  mymax = x;
  }
}else if (elementtype == "uchar") {
  for (size_t i=0; i<len; i += elesize) {
    char *r = data+i;
    x = static_cast<double>(*((unsigned char *)r));
    if (x > mymax)  mymax = x;
  }
}else if (elementtype == "short")

..etc..etc
于 2011-11-17T19:54:13.833 に答える
0

がループ不変であることを考えると、elementtypeの外側で 1 回だけ比較を行う方がよいでしょうfor。ちなみに、文字列リテラルと比較して意味のあるelementtypestd::stringまたは何かであることを願っています。

最終的には、処理ループ全体を実行するテンプレート関数を作成し、適切なテンプレート引数を使用して呼び出しますelementtype

于 2011-11-17T19:50:56.347 に答える
0

他の人が指摘したように、タイプは一度だけチェックする必要があります。次に、1 つのタイプのみを処理する適切なサブ関数を呼び出す必要があります。elementtype が double でない場合、my_max と比較するために double にキャストしないでください。そうしないと、不必要に double に変換され、double との比較が行われます。elementtype が uint の場合、何かを double に変換するべきではありません。これも uint である my_max var と比較してください。

于 2011-11-17T20:13:11.577 に答える