C# 十进制是如何工作的?

C# 十进制是如何工作的?,c#,decimal,C#,Decimal,我看了C#中的十进制,但我不是100%确定它的作用。 有损耗吗?在C#书写1.0000000000001f+1.0000000000001f时,当使用float时,会导致2(double获取您的2.0000000000000000002哪一个是正确的)是否可以用十进制数加上两个东西而不获得正确的答案 我可以使用多少个小数位?我看到最大值是79228162514264337593543950335但是如果我减去1,我可以使用多少个小数位 有什么怪癖我应该知道吗?在C#它的128位中,在其他语言中它

我看了C#中的十进制,但我不是100%确定它的作用。 有损耗吗?在C#书写
1.0000000000001f+1.0000000000001f
时,当使用
float
时,会导致
2
double
获取您的
2.0000000000000000002
哪一个是正确的)是否可以用十进制数加上两个东西而不获得正确的答案

我可以使用多少个小数位?我看到最大值是
79228162514264337593543950335
但是如果我减去1,我可以使用多少个小数位


有什么怪癖我应该知道吗?在C#它的128位中,在其他语言中它是多少位?它的工作方式是否与C#decimal相同?(加法、除法、乘法)

编程中的小数(几乎)永远不会100%准确。有时,最好是将十进制值乘以一个非常高的数字,然后再进行计算,但这仅限于您确保该值始终在0到100之间(因此不会超出maxvalue的范围)

浮动点本质上是不精确的。有些数字不能如实地表示出来。十进制是一个高精度的大浮点。如果您查看,您可以看到有“28-29个有效数字”。.NETFramework类与语言无关。在使用.net的每种语言中,它们的工作原理都是一样的



编辑(响应Jon Skeet):如果您使用上面的数字初始化Decimal类,每个数字在小数点后少于28位,那么只要二进制表示是精确的,数字就会被忠实地存储。因为它是64位格式的,所以我认为128位可以很好地处理它。有些数字,例如0.1,永远无法精确表示,因为它们是二进制的重复序列。

您显示的不是
decimal
,而是
float
。他们是非常不同的类型
f
float
的后缀,又名
m
decimal
的后缀,又名。你的问题不清楚你是否认为这实际上是使用了
decimal
,或者你只是用
float
来表达你的恐惧

如果使用1.0000000000001m+1.0000000000001m,则会得到正确的值。顺便说一句,请注意,
double
版本不能准确地表达任何一个单独的值

我在.NET中有关于这两种浮点的文章,您应该仔细阅读,以及其他参考资料:

  • (浮动/双重)
  • (十进制)
当然,所有浮点类型都有其局限性,但特别是您不应该期望二进制浮点精确地表示十进制值,例如0.1。它仍然不能表示任何不能用28/29位小数精确表示的东西,所以如果你用1除以3,你当然得不到确切的答案


您还应该注意,
十进制
的范围比
双精度
的范围小得多。因此,虽然它可以有28-29位小数精度,但不能表示真正的大数字(例如10200)或小数字(例如10-200)。

它糟糕吗?也许你应该先了解它想做什么,然后再把它写下来。或者你至少应该试着使用你抱怨的类型,然后再把它称为糟糕的:)@Jon-这个问题措辞很糟糕,但我相信他是在问
decimal
是否“糟糕”就像
float
因为加一个
float
有时是不“正确的”,我想他的意思是“有损的”@David&@Jon:也许我应该说“做加法和减法的时候是无损的”。该值很大,因此很难丢失乘法数据。我一直认为部门会丢失数据-编辑-Davy8!就是这个词!哎呀,它有损!十进制可以很容易地处理这种情况——它有足够的精度,并且它的基数是正确的。可惜OP实际上没有使用十进制。我还没有否决这个答案,但它确实应该更新,因为它给人的印象是,这个计算——当以十进制进行时——仍然是不准确的。它不会——它将保证给出准确的答案。“十进制是浮点标准的更大版本。”不,它不是。小数和浮点数代表不同的数据。这个答案不太正确,c代码有两种类型,请不要混淆!!!!!!!!!!你说decimal类,那么0.1永远不会是精确的可表示的,因为它们是二进制的重复序列-这与说1不能用int表示是一样的。decimal存储为基数10,而不是虚数2:)PRASHANT是对的-我没有发现最后的数字。0.1完全可以用十进制表示,这正是因为它是一个十进制浮点数而不是二进制浮点数。实际上,0.1只是1的尾数,指数为-1。C#中的十进制类型与浮点数不同。@TheBigO:是的
Decimal
是一种浮点类型。这是一种十进制浮点类型,但那是另一回事。@Jon Skeet:从技术上说你是对的。所以我将我的陈述修改为:十进制类型与C#中的浮点表示不同。@Martinho:或者换一种方式,double和float也是100%精确的,因为每个浮点或double值都是精确的值,精确地表示。这是对那些并非100%准确的值进行的操作:)@Downvoter:有什么评论吗?因为我可能误读了这个问题?我正要编辑。我敢打赌Downvoter不知道C#是十进制浮点类型。1200不是一个特别大的数字。你是说10200和10-200?我注意到你想知道我什么时候更新了我的问题。碰撞你抓住了f,我的意思是浮动。我现在才意识到有些人认为我说的是十进制。我主要想知道它是有损的还是无损的(我会排除除法和真正的大数值)