【问题标题】:Read n bytes in a char array and return it as a double读取 char 数组中的 n 个字节并将其作为双精度返回
【发布时间】:2016-12-22 01:48:06
【问题描述】:

我正在尝试读取 3D 图像,为此,我使用了一个库。 这个库告诉我数据的类型(int、float、double 等),并返回一个指向数据的 void 指针。我将其存储为 char*。

我正在创建一个方法,将 x,y,z 作为参数,并根据数据类型计算从 void 指针到请求的 x,y,z 值的偏移量。

但是,我现在需要转到“偏移”位置并读取 n 个字节(基于数据类型)并将值作为双精度返回(无论原始类型如何),但我不确定什么是最好的方法继续。

我最初考虑将 char* 指针转换为 int*、float*、double* 等...(基于数据类型),然后读取值 buffer[offset]。 但由于这是一个经常被调用的方法,我不确定每次都强制转换它是否有效。

谢谢。

编辑:这是一个 sn-p,但它不完全是真实的,因为我有多个类,等等......

class DataReader{
public:
  DataReader(const char* filename);
  ~DataReader();

  double GetValue(int x, int y, int z);

protected:
  MyImage im_;
  char* data_;
};

DataReader::DataReader(const char* filename)
{
   this->im_ = read_image(filename);
   this->data_ = (char*)im->data; // (return a void*)
}

DataReader::~DataReader()
{
}

double DataReader::GetValue(int x, int y, int z)
{
  int databytes = this->im_->bytes_per_voxel;
  int offset = z*100*100 + y*100 + x;

  double value = 0;
  // TODO: Get data from this->data_ at location 'offset'

  return value;
}

【问题讨论】:

  • 某个库通过其公共 API 为您提供void*?我不会称其为 C++ 库——也不是一件好事。你确定,你是在编写 C++ 而不是 C?
  • 铸造效率超高,能分享一下代码sn-p吗?
  • 如果你只是投射指针,那么成本几乎是 0
  • @whiteShadow 题外话,但你为什么坚持在你的代码中使用this->?它把事情弄得乱七八糟,没有必要。
  • 您是否尝试过使用自己的解决方案(第 4 段)并衡量性能?他们可以接受吗?

标签: c++ arrays pointers byte type-conversion


【解决方案1】:

您想使用相同的数据类型写入和读取内存。因此,如果您的图像存储为整数,请使用 int* 写入您的数据结构并使用 int* 从您的数据结构中读取。然后在最后一刻,将 data 转换为 double(而不是转换指针)。

【讨论】:

  • 这是 OP 在第 4 段中首先强调的内容。
  • 我不确定你的意思。对我来说,我创建了一个处理图像文件的类,我不希望用户担心其中的数据类型或格式。所以我的类总是返回双精度(因为这是最大精度,所以如果图像是双精度的,我不会丢失任何精度),但如果是整数,我也会将它作为双精度返回。我开始使用模板类做一些事情,但处理起来太乱了,因为我只知道运行时的数据类型。
  • 我打算为您推荐模板。如果您有许多数据类型要支持,那就是要走的路。当我提到数据结构时,我指的是底层图像,它看起来像存储在磁盘上。如果数据类型是 int,则将 int 放入其中(intPtr[offset]=intValue)并从中取出 int(intValue=intPtr[offset])。从数据结构或文件中取出整数后,将它们转换为双精度 (double dValue= static_cast(intValue));你显然还不关心效率,所以这应该很好用。
【解决方案2】:

以下内容应该可以满足您的需求,尽管它可能会被优化。如果您担心性能并经常调用它,我会考虑预加载数据并将其一次性重铸为一个数组,如果它不是太大而无法放入内存。仅供参考,您的所作所为似乎很奇怪,我无法想象,我看不出您将存储的数据值从较小的精度转换为较高的精度会获得什么。

double DataReader::GetValue(int x, int y, int z)
{
    int databytes = this->im_->bytes_per_voxel;
    int offset = (z*100*100 + y*100 + x)*databytes;//offset is now in bytes


    double value = 0;
    float rawValue;//We assume the values are stored as 4 byte floats. This will change for your particular problem. 

    memcpy(&rawValue, buffer[offset], databytes);
    value = rawValue;//Using implicit conversion, there may be a better way to do this.
    return value;
}

【讨论】:

  • 我这样做是因为我不希望用户必须处理多种数据类型。因此,无论图像的真实数据类型如何,我的 GetValue 都将始终返回双精度值。我选择了双精度,因为这是我的数据可以具有的最大精度,所以如果它们是双精度,我不会失去精度。如果数据是整数,它将没有用,但用户不必处理它。
  • 这会做同样的事情吗? int* ptr = static_cast<int*>(buffer[offset]); value = static_cast<double>(*ptr);
  • 图像处理使用 double 类型效率非常低。如果您遍历大图像中的每个像素,并且每个像素都有一个函数调用并使用 double 类型,那将是非常低效的。
  • Ceros,我不知道这是否重要,但我总是用 reinterpret_cast 投射指针
  • @Ceros 我不确定,但看起来静态转换确实执行了隐式转换。那么,OP,目前提交的两个答案缺少什么?
猜你喜欢
  • 2011-02-23
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 1970-01-01
  • 2013-03-10
  • 1970-01-01
  • 1970-01-01
  • 2021-05-13
相关资源
最近更新 更多