75919

How should I compare these doubles to get the desired result?

Question:

I have a simple example application here where I am multiplying and adding double variables and then comparing them against an expected result. In both cases the result is equal to the expected result yet when I do the comparison it fails.

static void Main(string[] args) { double a = 98.1; double b = 107.7; double c = 92.5; double d = 96.5; double expectedResult = 88.5; double result1 = (1*2*a) + (-1*1*b); double result2 = (1*2*c) + (-1*1*d); Console.WriteLine(String.Format("2x{0} - {1} = {2}\nEqual to 88.5? {3}\n", a, b, result1, expectedResult == result1)); Console.WriteLine(String.Format("2x{0} - {1} = {2}\nEqual to 88.5? {3}\n", c, d, result2, expectedResult == result2)); Console.Read(); }

And here is the output:

2x98.1 - 107.7 = 88.5 Equal to 88.5? False 2x92.5 - 96.5 = 88.5 Equal to 88.5? True

I need to be able to capture that it is in fact True in BOTH cases. How would I do it?

Answer1:

Floating point numbers often don't contain the exact value that mathematics tells us, because of how they store numbers.

To still have a reliable comparison, you need to allow some difference:

private const double DoubleEpsilon = 2.22044604925031E-16; /// <summary>Determines whether <paramref name="value1"/> is very close to <paramref name="value2"/>.</summary> /// <param name="value1">The value1.</param> /// <param name="value2">The value2.</param> /// <returns><c>true</c> if <paramref name="value1"/> is very close to value2; otherwise, <c>false</c>.</returns> public static bool IsVeryCloseTo(this double value1, double value2) { if (value1 == value2) return true; var tolerance = (Math.Abs(value1) + Math.Abs(value2)) * DoubleEpsilon; var difference = value1 - value2; return -tolerance < difference && tolerance > difference; }

Please also make sure to read <a href="http://realtimecollisiondetection.net/blog/?p=89" rel="nofollow">this blog post</a>.

Answer2:

If you need more precision (for money and such) then use decimal.

var a = 98.1M; var b = 107.7M; var c = 92.5M; var d = 96.5M; var expectedResult = 88.5M; var result1 = (2 * a) + (-1 * b); var result2 = (2 * c) + (-1 * d); Console.WriteLine(String.Format("2x{0} - {1} = {2}\nEqual to 88.5? {3}\n", a, b, result1, expectedResult == result1)); Console.WriteLine(String.Format("2x{0} - {1} = {2}\nEqual to 88.5? {3}\n", c, d, result2, expectedResult == result2));

Output:

2x98.1 - 107.7 = 88.5 Equal to 88.5? True 2x92.5 - 96.5 = 88.5 Equal to 88.5? True

Answer3:

It's a problem with how floating point numbers are represented in memory.

You should read this to get a better understanding of whats going on: <a href="http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html" rel="nofollow">What Every Computer Scientist Should Know About Floating-Point Arithmetic</a>

Answer4:

Simply change your rounding to level 2 , this will give TRUE

double result1 =Math.Round ( (1 * 2 * a) + (-1 * 1 * b),2);

Answer5:

using Math.Round() will round result1 to the correct decimal

result1 = Math.Round(result1, 1);

Answer6:

using the debugger,

result1=88.499999999999986; expectedResult = 88.5

So when using the double ,these are not equal.

Answer7:

There is a whole school of thought that is against using Double.Epsilon and similar numbers...

I think they use this: (taken from <a href="https://stackoverflow.com/a/2411661/613130" rel="nofollow">https://stackoverflow.com/a/2411661/613130</a> but modified with the checks for IsNaN and IsInfinity suggested <a href="http://social.msdn.microsoft.com/Forums/vstudio/en-US/b6684987-9934-4798-9113-eb6a39efe1a6/doubleepsilon-what-is-it-good-for" rel="nofollow">here</a> by nobugz

public static bool AboutEqual(double x, double y) { if (double.IsNaN(x)) return double.IsNaN(y); if (double.IsInfinity(x)) return double.IsInfinity(y) && Math.Sign(x) == Math.Sign(y); double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15; return Math.Abs(x - y) <= epsilon; }

The 1E-15 "magic number" is based on the fact that doubles have a little more than 15 digits of precision.

I'll add that for your numbers it returns true :-)

Recommend

  • Python基础介绍(一)
  • Make PyCharm alert to reload files when they're changed externally
  • Tracking AJAX error on readystate 0, status 0 and statusText error
  • How can a function find a parent element of the anchor which originally called the function?
  • Is it possible to serialize string to json with single slashes?
  • How to paginate or infinite scroll by number of items in firestore?
  • Left join on date range by group ID
  • How to handle mongoose error with nestjs
  • React Linting: Unclosed Regular Expression
  • Git objects SHA-1 are file contents or file names?
  • javax.el.ExpressionFactory Error when running Spring Boot Application on Google App Engine Standard
  • Migrating MOSS 2007 from SQL 2000 to SQL 2005 [closed]
  • What is the correct way to combine two UserControls into one with two states?
  • Open a cmd program with full functionality (i/o)
  • How to smoothly connect two signals in matlab [closed]
  • dmtracedump doesn't work, HELP!
  • ASP.NET GridView throws: The version of SQL Server in use does not support datatype 'date'
  • Bundling python(“.py”)files along with java class files for a web application
  • How does the dispatcher work when mixing sync/async with serial/concurrent queue?
  • Query regarding com.jcraft.jsch.JSchException: UnknownHostKey: x.y.com. DSA key fingerprint is “ac:e
  • Optimization of optim() in R ( L-BFGS-B needs finite values of 'fn')
  • .Net core Hosted Services guaranteed to complete
  • Create an Office365 mailbox from within C# Web API method
  • Disable account chooser FirebaseUI React
  • Separating definition/instantiation of template classes without 'extern'
  • How to create subsets of a single set of elements with XSLT?
  • Another “Cannot make static reference…” Question
  • What is the best way to cache and reuse immutable singleton objects in Java?
  • calling IO Operations from thread in ruby c extension will cause ruby to hang
  • Capture SIGFPE from SIMD instruction
  • Using Service Component Runtime
  • Jersey serializes character value to ASCII equivalent numeric string
  • How do I use TagLib-Sharp to write custom (PRIV) ID3 frames?
  • media foundation H264 decoder not working properly
  • CAS 4 - Not able to retrieve the LDAP groups after successful authentication