首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >比较从双精度数转换的小数是否安全

问比较从双精度数转换的小数是否安全
EN

Stack Overflow用户
提问于 2017-05-12 12:46:41
回答 5查看 324关注 0票数 3

众所周知,使用==运算符比较双精度值是不安全的。在此示例中,它返回false:

代码语言:javascript
复制
double d1 = 0.11;
double d2 = 0.44 - 0.33;
Console.WriteLine(d1 == d2);

但是,如果我们将值转换为decimal,它将返回true:

代码语言:javascript
复制
double d1 = 0.11;
double d2 = 0.44 - 0.33;
Console.WriteLine((decimal)d1 == (decimal)d2);

比较double类型的小数是否总是安全的,或者在某些情况下可能会产生意想不到的结果?

更新:Hossein的例子很好,它表明它可能是错误的。但我更感兴趣的是,是否有相反的例子,当我们期望十进制值相等,但它们不是。更广泛地说,当我们从双精度转换为小数时,究竟发生了什么。

EN

回答 5

Stack Overflow用户

发布于 2017-05-12 14:35:06

众所周知,在.net中比较双精度值是不安全的。在本例中,它返回false

你搞错了什么是不安全的。

假设任意十进制表示法,即使它很短(以十进制写成),也完全用二进制浮点表示,这是不安全的。假设二进制浮点值之间的-生成与数学结果最接近的可表示浮点值以外的任何值都是不安全的(特别是,假设它总是生成数学结果是不安全的)。

d1 == d2是完全安全的,(decimal)d1 == (decimal)d2也是如此。第一个不会总是返回你想要的东西,但第二个也不会,因为它没有理由根据上面列出的原则。一旦计算了d1和d2,就已经完成了近似:

  • representation近似值,因为您似乎认为0.11应该是数学值11/100,但事实并非如此,它是最接近的可表示value;
  • operation近似值,因为0.44减去0.33的数学结果可能无法精确表示,在这种情况下将使用最接近的可表示值。

事实是,这些近似值是复合的,当在C#中添加转换为decimal的第三个近似值时,会产生您所期望的值,这纯粹是巧合。如果有什么是众所周知的,那就是在近似值发生后修复它已经太晚了,而且添加另一个近似值并没有真正的帮助。请参阅本文中的第一个示例Excel,它是微软的另一个可编程产品。

票数 2
EN

Stack Overflow用户

发布于 2017-05-12 13:03:03

在这种情况下,您可能会得到想要的结果,但通常您的答案是NO。如果将一个值存储在double中,然后将其转换为小数,并不会提高其精度(link)。

考虑下面的例子。等式返回true,但我们期望返回false。

代码语言:javascript
复制
double myDouble1 = 0.11;
double myDouble2 = 0.10999999999999999;
Console.WriteLine((decimal)myDouble1 == (decimal)myDouble2); //true, but we expect false

但是如果您将这些值存储为十进制,那么您将获得正确的结果。

代码语言:javascript
复制
decimal myDecimal1 = 0.11M;
decimal myDecimal2 = 0.10999999999999999M;
Console.WriteLine(myDecimal1 == myDecimal2); //false
票数 1
EN

Stack Overflow用户

发布于 2017-05-12 13:02:55

它总是安全的,提供了你知道浮点类型和小数类型之间的转换语义,和识别对实现代码的影响。

也就是说,除非您有充分的理由进行强制转换,否则遵循标准方法检查某些给定容差的相等性会更安全。(例如,(0.999 - 1.00) < 0.01。)

来自Explicit Numeric Conversions Table (C# Reference)

  • 当您将浮点数或双精度数转换为小数时,源值将转换为小数表示形式,并根据需要四舍五入到小数点后的第28位最接近的数字。根据源值的值,可能会出现以下结果之一:

代码语言:javascript
复制
- If the source value is too small to be represented as a decimal, the   result becomes zero.
- If the source value is NaN (not a number), infinity, or too large to   be represented as a decimal, an OverflowException is thrown.
- When you convert decimal to float or double, the decimal value is   rounded to the nearest double or float value.

​

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43929468

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档