十进制在 C# 中存储解析字符串的精度?有什么影响
本文关键字:精度 影响 什么 字符串 存储 十进制 | 更新日期: 2023-09-27 18:19:11
在IRC上的一次对话中,有人指出了以下内容:
decimal.Parse("1.0000").ToString() // 1.0000
decimal.Parse("1.00").ToString() // 1.00
decimal
类型如何/为什么保持这样的精度(或者更确切地说,有效数字(?我的印象是这两个值是相等的,而不是不同的。
这也引发了进一步的问题:
- 在数学运算过程中如何确定有效数字的数量?
- 在序列化过程中是否保留有效数字的数量?
- 当前的文化是否会影响处理此问题的方式?
在数学运算过程中如何确定有效数字的数量?
这在 ECMA-334 C# 4 规范 11.1.7 p.112 中指定
小数表示为按 10 的幂缩放的整数。为 绝对值小于 1.0m 的小数,该值精确到 至少小数点后 28 位。对于具有绝对值的小数 大于等于1.0m,该值精确到至少28 数字。
在序列化过程中是否保留有效数字的数量?
是的,确实如此,通过序列化,值及其精度不会改变
[Serializable]
public class Foo
{
public decimal Value;
}
class Program
{
static void Main(string[] args)
{
decimal d1 = decimal.Parse("1.0000");
decimal d2 = decimal.Parse("1.00");
Debug.Assert(d1 ==d2);
var foo1 = new Foo() {Value = d1};
var foo2 = new Foo() {Value = d2};
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("data.bin", FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, d1);
stream.Close();
formatter = new BinaryFormatter();
stream = new FileStream("data.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
decimal deserializedD1 = (decimal)formatter.Deserialize(stream);
stream.Close();
Debug.Assert(d1 == deserializedD1);
Console.WriteLine(d1); //1.0000
Console.WriteLine(d2); //1.00
Console.WriteLine(deserializedD1); //1.0000
Console.Read();
}
}
当前的文化是否会影响处理此问题的方式?
当前区域性仅影响从字符串解析小数的方式,例如,它可以将"."或",">作为区域性特定的小数点符号或货币符号进行处理,如果您提供它,例如"£123.4500"。区域性不会更改对象在内部的存储方式,也不会影响其精度。
在内部,十进制有一个尾数、一个指数和一个符号,所以没有空间容纳其他任何东西。
十进制由 96 位整数和比例因子(小数点后的位数(组成,范围为 0 到 28。 因此:
- 比例因子为 3 时,1.000 变为 1000。
除了我在这里看到的帖子之外,我个人还会添加一个旁注:
在使用浮点/小数/双精度数的持久性操作期间,始终考虑您所在culture
,否则您将要保存。像这里编写的代码是第一个,但最终传递到完全混乱和非文化独立的架构。
使用 Decimal.Parse(字符串,IFormatProvider(。
在我看来,必须从库中删除缺少Culture
参数的方法(Parse From/To
(,以迫使开发人员考虑这个非常重要的方面。