我有一个正在序列化的对象,它包含大量的替身和替身结构,我正在通过protobuf-net发送这些替身和结构。问题是,隔着电线,我不需要那么精确。
例如,我有这样的东西,一个外部库正在返回一个double。
double Volts = Sampler.GetValue(); //Volts is a value like 4.35(...)
但我真的只需要两个小数点的精度。通过导线将其编码为双精度需要64位。将其编码为具有2位小数精度的字符串("4.35")实际上可能占用较少的空间。但我在双方都有转换问题需要处理。
我一直在探索v2选项,但我还没有看到这样的功能。我可以看到,如果可以将浮点值编码为可变长度的精度,它可以节省大量空间。
我曾想过将其乘以一个整数,然后在远端将其转换回,但据我所知,这需要我对基类对象进行重大更改(我在反序列化过程中使用了merge选项)。
有什么想法或聪明的解决办法吗?
顺便说一句,protobuf网络具有强大的可配置性。谢谢你制作了这么棒的节目。
进行"也许将它们作为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)都可以准确地存储。
如果您希望固定精度,另一种选择是使用倍数。例如:
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个字节作为"变量"。
将数据序列化为字符串听起来是个坏主意。
双精度值已经只有64位(请参阅Protocol Buffers编码,有线类型1),文本以UTF-8传输,因此即使在4.35的简化示例中,也需要32位才能传输,更不用说在反序列化时将其转换回双精度值的努力,以及当有人查看该代码时的一般维护噩梦了。
如果您不需要精度,我建议使用浮点,它只使用32位,但在使用这些值及其序列化时保持一致。