C#Protobuf net:小数字典:零不';我不能正常往返
我在protobuf net中发现了一个关于十进制零的序列化/反序列化的奇怪错误,我想知道是否有人找到了一个很好的解决方法,或者这是否真的是一个特性 给定一个如上所述的字典,如果我在linqpad中运行:C#Protobuf net:小数字典:零不';我不能正常往返,c#,decimal,protobuf-net,C#,Decimal,Protobuf Net,我在protobuf net中发现了一个关于十进制零的序列化/反序列化的奇怪错误,我想知道是否有人找到了一个很好的解决方法,或者这是否真的是一个特性 给定一个如上所述的字典,如果我在linqpad中运行: void Main() { { Dictionary<string, decimal> dict = new Dictionary<string, decimal>(); dict.Add("one", 0.0000000m);
void Main()
{
{
Dictionary<string, decimal> dict = new Dictionary<string, decimal>();
dict.Add("one", 0.0000000m);
DumpStreamed(dict);
}
{
Dictionary<string, decimal> dict = new Dictionary<string, decimal>();
dict.Add("one", 0m);
DumpStreamed(dict);
}
}
public static void DumpStreamed<T>(T val)
{
using (var stream = new MemoryStream())
{
Console.Write("Stream1: ");
ProtoBuf.Serializer.Serialize(stream, val);
foreach (var by in stream.ToArray())
{
Console.Write(by);
}
Console.WriteLine();
Console.Write("Stream2: ");
stream.Position = 0;
var item = ProtoBuf.Serializer.Deserialize<T>(stream);
using(var stream2 = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(stream2, item);
foreach (var by in stream2.ToArray())
{
Console.Write(by);
}
}
}
Console.WriteLine();
Console.WriteLine("----");
}
有人知道为什么零只在反序列化过程中得到规范化,而不是在序列化过程中得到规范化吗
或者,在序列化/反序列化的字典中,是否有一致地规范化或不一致地规范化十进制零的解决方法 浮点数据类型实际上是包含多个元素的结构。其中包括基准值和将基准值提升到的指数。十进制的c#文档说明如下: 十进制数的二进制表示法由1位符号、96位整数和用于分割整数并指定其小数部分的比例因子组成。比例因子隐式地是数字10,其指数范围为0到28 例如,您可以将1234000表示为
- 基值为1234000 x 10^0
- 基值为123000 x 10^1
- 基值为12300 x 10^2
public static unsafe string ToBinaryHex(this decimal This)
{
byte* pb = (byte*)&This;
var bytes = Enumerable.Range(0, 16).Select(i => (*(pb + i)).ToString("X2"));
return string.Join("-", bytes);
}
是的;问题在于这句善意但可能有害的话:
if (low == 0 && high == 0) return decimal.Zero;
它忽略了检查signScale
。它应该是:
if (low == 0 && high == 0 && signScale == 0) return decimal.Zero;
我将在下一个版本中对此进行调整
(编辑:我最终完全删除了该检查-代码的其余部分只是一些整数移位等,因此拥有“分支”可能比没有更昂贵)添加了完整的代码块,对此表示抱歉。重要的不是保留零,而是生成的字节流的差异。产生的字节流是不同的,这导致字典周围的误报是不同的。(为“长尾”交叉引用github问题):;protobuf net已经在使用
GetBits
etc,并且知道scale.Hi@marcGravel。我想你在读我的答案,好像它是写给你的。这封信是写给OP的,他把二进制等式和数字等式混为一谈,结果可能是灾难性的;他们只是希望它能够按可预测的方式往返,这是非常合理的。请注意,重要性并不是保持零,而是更多地体现在生成的字节流之间的差异。产生的字节流是不同的,这导致字典周围的误报是不同的。请考虑在你已经很好的回答这方面的评论。老实说,我更关心的是,它悄悄地改变数据的事实;这实际上不是假阳性——而是真阳性:数据不同(无效);你的回答解释了为什么他们可能认为这是假阳性,而实际上是真阳性,但是。。。我宁愿修改代码,使其成为真正的负数:)
if (low == 0 && high == 0 && signScale == 0) return decimal.Zero;