我有一个对象,我正在序列化,其中包含很多双打和双打结构,我正在使用protobuf-net通过线路发送。问题在于,我不需要全部精确度。
例如,我有类似这样的东西,外部库返回一个双。
double Volts = Sampler.GetValue(); //Volts is a value like 4.35(...)
但我真的只需要两个小数点的精度。将其作为双线进行编码,需要64位。将其编码为具有2位小数精度(“4.35”)的字符串实际上可能占用更少的空间。但后来我在任何一方都要处理转换问题。
我一直在讨论v2选项,我还没有看到这样的功能。如果你可以将浮点值编码为可变长度的精度,我可以看到如何节省大量空间。
我已经考虑过乘以一个整数发送它然后将它转换回远端,但据我所知,这需要我对我的基类对象进行重大更改(我是在反序列化期间使用合并选项。)
任何想法或聪明的工作?
顺便说一句,protobuf-net非常棒,可配置性很强。谢谢你们制作了这么棒的节目。答案 0 :(得分:2)
将数据序列化为字符串听起来不错。
双值已经分别只有64位(见Protocol Buffers encoding,线型1),文本传输为UTF-8,所以即使在4.35的简化示例中,你需要32位传输,更不用说在反序列化时将其转换为双倍的努力以及当有人查看该代码时的一般维护噩梦。
如果您不需要精度,我建议使用浮点数而不是仅使用32位,但在使用这些值及其序列化时保持一致。
答案 1 :(得分:2)
继续“可能将它们作为float
”进行讨论,你可以很容易地做到这一点,实际上;例如,如果您目前有:
[ProtoMember(4)]
public double Value {get;set;}
您可以将其更改为:
public double Value {get;set;} // this won't be serialized directly
[Protomember(4)] // but we'll use this private property for the serialization
private float ValueSingle {
get { return (float)Value; }
set { Value = value; }
}
它将在后台为你做垫片。此特定更改也应与现有数据兼容(虽然从技术上讲它确实会更改.proto架构,但protobuf-net相当宽容)。这将需要4个字节。另请注意,IEEE754一如既往地适用与protobuf-net完全无关,无法保证任何特定值(例如4.35)可以完全存储。< / p>
如果你想要固定精度,另一种选择是使用倍数。例如:
public double Value {get;set;}
[ProtoMember(4)]
public int ValueInt32 {
get { return (int)Math.Round(100 * Value); }
set { Value = value/100.0; }
}
你必须进行测试,看看它是否与旧数据兼容......这是一个更大的变化。这里,4.35将作为435发送,它将2个字节作为“varint”。