C# 为什么这个小数点在ToString()上显示8个小数位?
我有一个C# 为什么这个小数点在ToString()上显示8个小数位?,c#,sql-server,entity-framework,decimal,C#,Sql Server,Entity Framework,Decimal,我有一个decimal类型的变量,其值为1.0。我将其保存到SQL Server 2012表中的一列中,该表的类型为decimal(10,8) 检索该值后,我看到它是1,但当我调用ToString()时,返回的值是“1.00000000”(见下文) 我意识到8位小数对应于数据库中的数据类型。然而,实体框架生成的属性中没有赋予它这种行为的属性或任何东西,所以我不知道这是如何发生的 以下是我在即时窗口中执行的一些测试: myDecimal 1 myDecimal.ToString() "1.0000
decimal
类型的变量,其值为1.0
。我将其保存到SQL Server 2012表中的一列中,该表的类型为decimal(10,8)
检索该值后,我看到它是1,但当我调用ToString()
时,返回的值是“1.00000000”
(见下文)
我意识到8位小数对应于数据库中的数据类型。然而,实体框架生成的属性中没有赋予它这种行为的属性或任何东西,所以我不知道这是如何发生的
以下是我在即时窗口中执行的一些测试:
myDecimal
1
myDecimal.ToString()
"1.00000000"
myDecimal == 1
true
myDecimal == 1.0m
true
正如您从上两次测试中所看到的,这也不是浮点错误(这不是我所期望的,因为十进制是定点的,但我必须尝试一下,因为我没有想法了)
知道小数的ToString()
是如何产生一个带8位小数的字符串的吗
编辑:要进行比较,请查看下面的测试
1m.ToString()
"1"
没错,十进制(10,8)告诉DB发回8个小数点
如果您将结果指定给一个数字类型,那么它只是一个数字,而不填充它本身将是最小的表示形式
当您在数据库对象上执行ToString时,它正输出从SQL server返回的内容,在本例中是1加8零
您可以通过直接查询数据库服务器来确认这一点。如果您使用的是database first EntityFramework,则会将edmx文件中的列属性以xml格式保留为
<Property Name="ColumnName" Type="Decimal" Precision="8" Scale="4" Nullable="false" />
原因是十进制类型没有规范化。同一个数字有多个表示形式,这些表示形式将表示为不同的字符串 这不是数据库类型的特殊属性,这是decimal的正常工作方式。没有特殊的DataAnotation或任何附加到变量的内容
(1m).ToString() == "1"
(1.00000000m).ToString() == "1.00000000"
((1m)==(1.00000000m)) == true
对于给定的双精度,只有一个有效表示,即尾数*2指数的一个组合
对于十进制,尾数*10指数有多个有效表示形式。每个表示相同的数字,但在将十进制转换为字符串时,通过多个可能的表示形式提供的附加信息用于选择尾随数字的默认数量。确切的细节并没有很好的记录,我也没有发现关于小数相加或相乘时指数到底发生了什么的信息。但是它对ToString()的影响很容易验证
缺点是Equals()和GetHashCode()操作比标准化数字格式更复杂,并且在实现中存在一些细微的错误:
:
十进制数以128位存储,尽管严格来说只有102位
必要的。把十进制作为三位32位是很方便的。
表示尾数的整数,然后一个整数表示尾数
符号和指数。最后一个整数的顶部位是符号位
(以正常方式,为负数设置位(1)
位16-23(高16位字的低位)包含
指数。其他位必须全部清除(0)。此表示是
由decimal.GetBits(decimal)给出的值,它返回一个4的数组
ints。
[……]
decimal类型本身不规范化-它会记住它有多少个十进制数字(尽可能保持指数),并且在格式化时,零可能被算作有效的十进制数字
您可以通过比较decimal.GetBits()返回的值来验证您拥有的两个小数是否相同,即:
使用这种行为格式化小数可能很有诱惑力,但我建议在转换为字符串时始终明确选择精度,为了避免混淆和不可预见的意外情况,例如,如果事先将数字乘以某个因子。当Entity Framework从查询返回的结果中检索值时,它使用EDMX定义或数据注释来了解小数点的精度设置 由于您使用了十进制(10,8),Entity Framework将您的十进制值设置为
1.00000000
。在十进制中执行ToString
将尊重该精度,并输出所有被认为重要的零
所使用的类型仍然是十进制
。您可以通过为小数指定精确值来指定精度:1.000m
比1.0m
更精确。这就是十进制的工作原理,下面(简要)提到了它
<>代码> toStase不知道在你告诉它之前,你不认为零是重要的。零仍然是一个值。@Tanner它不是重复的;我知道如何格式化字符串,如果我想。。。我问的是8位小数的默认格式是如何设置的。@Gigi因为您的列定义指定了8位小数的精度,如果它们不都是零,那么删除它们就会失去精度。c#是否应该知道您希望
1.00000000
被表示为1.0
,而不需要您告诉它?如果它是1.12345678
,您是否希望c#在默认情况下返回1.1
。例如,1.000表示与1.0不同的值:1.000可以是1+/-0.0005,而1.0可以是1+/-0.05。@Gigi请计算yourDecimal.GetType()
,以获取有关十进制值的所有基本信息,并意识到它不仅仅存储数字,即使你说“给我数值”时,即时窗口显示的就是这些。@Tanner请注意,我的问题正是关于十进制(“不仅仅是一个数字”)如何转换为特定格式的stri
(1m).ToString() == "1"
(1.00000000m).ToString() == "1.00000000"
((1m)==(1.00000000m)) == true
decimal.GetBits(1m) == {int[4]}
[0]: 1
[1]: 0
[2]: 0
[3]: 0
decimal.GetBits(1.00000000m) == {int[4]}
[0]: 100000000
[1]: 0
[2]: 0
[3]: 524288