Double数据类型无法正确表示某些基数为10的值。这是因为浮点数代表实数。这意味着当表示货币值时,应该使用十进制值类型来防止错误。 (随意纠正本序言中的错误)
我想知道的是,在标准.Net框架中64位架构下的双数据类型下出现此类问题的值是什么(C#如果有所不同)?
我希望答案是一个公式或规则来找到这样的值,但我也想要一些示例值。
答案 0 :(得分:7)
任何不能写为2的正负幂之和的数字都不能精确地表示为二进制浮点数。
浮点数的公共IEEE formats for 32位和64位表示形成了进一步的约束;它们限制有效数和指数中的二进制数字的数量。因此,存在最大和最小可表示数字(如果存储器服务,则大约+/- 10 ^ 308(基数-10))并且限制可以表示的数字的精度。这种精度限制意味着,对于64位数字,最大功率2的指数与数字中最小功率之间的差值限制为52,因此,如果您的数字包含2 ^ 52中的项,则可以也包括一个2 ^ -1的术语。
无法在二进制浮点数中精确表示的数字的简单示例包括1/3
,2/3
,1/5
。
由于浮点数集合(在任何表示中)是有限的,并且实数集合是无限的,因此找到不能完全表示为浮点数的实数的一种算法是选择a实数随机。实数可以精确表示为浮点数的概率为0
。
答案 1 :(得分:1)
这个问题实际上超越了任何单一的编程语言或平台。这种不准确性实际上是二进制数据所固有的。
考虑到使用double,小数点左边的每个数字N(基于0的索引I)表示值N * 2 ^ I,小数点右边的每个数字表示值N * 2 ^( - I)
。例如,5.625(基数10)将是101.101(基数2)。
鉴于此计算,并且对于不同的I值,无法计算为2 ^( - I)之和的十进制值将具有不正确的值作为double。
答案 2 :(得分:1)
您通常需要做好准备,以确保double
中存储的任何值都有少量错误。除非你存储一个常量值,否则它可能至少会出现一些错误。如果必须没有任何错误,并且值不是常量,那么您可能不应该使用浮点类型。
在许多情况下,您可能应该问的是,“我如何处理次要浮点错误?”您将想知道哪些类型的操作可能导致大量错误,哪些类型不会导致错误。你需要确保比较“平等”的两个值实际上只是确保它们“足够接近”而不是完全相等,等等。
答案 3 :(得分:1)
浮动在以下公式中表示为s
,e
和m
s * m * 2^e
这意味着无法使用给定表达式(以及s
,e
和m
的相应域中)无法表示的任何数字都无法准确表示。
基本上,您可以表示0
和2^53 - 1
之间的所有数字乘以一定的2的幂(可能是负幂)。
例如,0
和2^53 - 1
之间的所有数字都可以用2^0 = 1
表示。您还可以将所有这些数字除以2
(.5
分数)。等等。
这个答案并没有完全涵盖这个主题,但我希望它有所帮助。