C# Getting strange results for a simple math operations

最后都变了- 提交于 2019-12-01 20:33:55

Floating point arithmetic is not precise. You should read the article What Every Computer Scientist Should Know About Floating-Point Arithmetic. If you want your calculations to be precise in a decimal sense, you should use the decimal type, where 0.1m + 0.7m == 0.8m is true. You should note that decimal uses floating point numbers just like float and double, except that the base is 10, not 2. Since dealing with base 2 is so much easier and highly-optimized, decimal is much slower. It also has its own inaccuracies, it's only precise when dealing with numbers that can be represented in a short number of decimal digits (like 0.7 and 0.1), making it good for financial data.

Another useful article to understand floating point numbers is Wikipedia's Double-precision floating-point format.

Call the Math.Round method to ensure that both values have the same precision. The following example modifies a previous example to use this approach so that two fractional values are equivalent:

using System;

public class Example
{
   public static void Main()
   {
      double value1 = .333333333333333;
      double value2 = 1.0/3;
      int precision = 7;
      value1 = Math.Round(value1, precision);
      value2 = Math.Round(value2, precision);
      Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2));
   }
}
// The example displays the following output: 
//        0.3333333 = 0.3333333: True

Here is the answer: http://www.codeproject.com/Articles/383871/Demystify-Csharp-floating-point-equality-and-relat

Floating values are only approximations. To compare two floating point values you need to check the difference between them. The difference cannot be greater than float.Epsilon

Use this to compare these values:

bool AlmostEqualDoubles(double nVal1, double nVal2, int nPrecision = 6)
{
   nPrecision = Math.Max(Math.Min(16, nPrecision), 0);
   double nEpsilon = 1.0;
   for (int i = 0; i < nPrecision; i++) nEpsilon *= 0.1;       
   return (nVal2 - nEpsilon) < nVal1 && nVal1 < (nVal2 + nEpsilon);
}

internally, a double is stored in bits, in base-2. All integers can be represented exactly in base-2, but when it comes to fractions, it;s another matter all together.

The same way that we cannot precisely respresent the result of 1/3 in our decimal system, in a binary system you cannot represent all fractions. Since decimal is base-10, it is easy to represent x/10 in decimal, but in base-2, it is impossible for some x.

So whenever you use doubles, always be aware of some rounding errors.

For this reason, doubles are not to be used whenever exact numbers are required, as with monetary amounts.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!