首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Marshal C++ float to C# float精度问题

问Marshal C++ float to C# float精度问题
EN

Stack Overflow用户
提问于 2011-02-24 02:16:51
回答 2查看 2K关注 0票数 1

我有一个DBase IV数据库。每一行都有一个包含ASCII编码字符串的memo字段,该字符串包含两个序列化的borland c++结构。我可以使用OleDb提取数据,使用ASCIIEncoding类将其重新编码为ascii,使用BinaryReader将其转换为字节,并使用Marshal.PtrToStructure将其转换为我的C#结构。我得到的数据是正确的,但数据库中任何过大的浮点数在转换为c#时都是完全错误的。例如,值1149.00转换为764.9844,但像64.00值转换为fine。我可以发布一些代码和结构,但我认为我一开始尽量保持简短。我知道浮点数只能精确到7位数,但我不明白为什么我会看到这种情况,因为这些值都在这个限制之下。

编辑:

代码语言:javascript
复制
struct cplusplusstruct // from the c++ code
{
  int   Number;
  float P;
  float ZP;
  float Hours;
  int   Month;
  int   Day;
  int   Year;
  int   Hour;
  int   Minute;
  int   Second;
  ULONG UPCTime;
  int   B;
  char  Name[21];
  float L;
  float H;
  float S;
}


[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct csharpstruct  //The C# struct I created
{
     public int Number;
     public float Pr;
     public float ZP;
     public float Hours;
     public int Month;
     public int Day;
     public int Year;
     public int Hour;
     public int Minute;
     public int Second;
     public UInt32 UPCTime;
     public int B;
 [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 21)]
     public string Name;
     public float L;
     public float H;
     public float S;
 }


//OLE DB Connection and query ...

//Casting data to struct
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] blob = encoding.GetBytes(memoString);
MemoryStream memoryStream = new MemoryStream(blob);
BinaryReader binaryReader = new BinaryReader(memoryStream);

int dataSize = Marshal.SizeOf(typeof(csharpstruct));
GCHandle handle = GCHandle.Alloc(binaryReader.ReadBytes(dataSize), GCHandleType.Pinned);
csharpstruct data = (csharpstruct) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(csharpstruct));

编辑:下面的java代码可以很好地读取数据,但没有使用任何强制转换。

代码语言:javascript
复制
org.xBaseJ.DBF dbf = new org.xBaseJ.DBF(dbPath);
org.xBaseJ.DBF dbf = new org.xBaseJ.DBF(dbPath);
MemoField m = (MemoField) dbf.getField("MEMOFIELD");

Charset charset = Charset.forName("US-ASCII");
CharsetDecoder decoder = charset.newDecoder();
ByteBuffer trendBytes = ByteBuffer.wrap(m.getBytes());
trendBytes.order(ByteOrder.LITTLE_ENDIAN);
trendBytes.getInt();
trendBytes.getFloat();
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-09 00:34:17

我不能直接解决这个问题。问题似乎来自我使用的OLE数据提供程序。从数据库中检索的数据与xBaseJ提供的数据略有不同。我最终使用IKVM.NET将xBaseJ转换为CLI字节码。这使我可以用xBaseJ阅读器替换OLE数据提供程序。我的其余代码保持不变。

票数 0
EN

Stack Overflow用户

发布于 2011-02-24 05:45:31

您的C#结构中有Pack = 1,但没有说明您的C++结构是否打包。因为你在你的浮点数之前有一个奇数大小的字段(21个字符的字符串),这可能会引起麻烦,并意味着你的浮点数正在被错误地读取。之前的所有东西都是4字节长的,所以打包不太可能给你带来问题。在继续之前,我会确保包装在C#和C++中都是匹配的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5095158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档