www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Confusion Concerning Numerical Equation

reply Avery Stupidman <stupidman stupid.man> writes:
Hello,

I have a function "angle" that returns the angle (in degrees) of 
a right triangle given the length of the its lengths as type 
"real". It works, but when trying to test the equality of the 
angle with the seemingly identical value, I'm informed that the 
two are not equal. Thus, when angleDeg(sqrt(3.0)/2.0, 1.5) 
returns 60, the comparison "angleDeg(sqrt(3.0)/2.0, 1.5) == 60" 
resolves to false.

I'm most likely stupid and sleep deprived, but if I may have some 
elucidation, I'd be very grateful.

Some code:

real angleDeg(real x, real y)
{
	import std.math : PI, abs, atan2, sgn;

	auto angle = atan2(y, x);
	
	// Simplify angle if vector resides in quadrants II or III
	if (x < 0)
	{
		angle = (PI - abs(angle)) * sgn(angle);
	}

	return angle * 180 / PI;
}

import std.math : sqrt;

assert(angleDeg(sqrt(3.0)/2.0, 1.5) == 60.0); // Fails
Nov 16 2019
next sibling parent Avery Stupidman <stupidman stupid.man> writes:
Typo in the first paragraph: angle -> angleDeg
Nov 16 2019
prev sibling next sibling parent reply drug <drug2004 bk.ru> writes:
16.11.2019 13:01, Avery Stupidman пишет:
 Hello,
 
 I have a function "angle" that returns the angle (in degrees) of a right 
 triangle given the length of the its lengths as type "real". It works, 
 but when trying to test the equality of the angle with the seemingly 
 identical value, I'm informed that the two are not equal. Thus, when 
 angleDeg(sqrt(3.0)/2.0, 1.5) returns 60, the comparison 
 "angleDeg(sqrt(3.0)/2.0, 1.5) == 60" resolves to false.
 
 I'm most likely stupid and sleep deprived, but if I may have some 
 elucidation, I'd be very grateful.
 
 Some code:
 
 real angleDeg(real x, real y)
 {
      import std.math : PI, abs, atan2, sgn;
 
      auto angle = atan2(y, x);
 
      // Simplify angle if vector resides in quadrants II or III
      if (x < 0)
      {
          angle = (PI - abs(angle)) * sgn(angle);
      }
 
      return angle * 180 / PI;
 }
 
 import std.math : sqrt;
 
 assert(angleDeg(sqrt(3.0)/2.0, 1.5) == 60.0); // Fails
In general you shouldn't compare floating point values for equality because of their nature, you can use something like approxEqual https://dlang.org/library/std/math/approx_equal.html P.S. see also https://floating-point-gui.de/errors/comparison/
Nov 16 2019
parent Avery Stupidman <stupidman stupid.man> writes:
On Saturday, 16 November 2019 at 10:17:12 UTC, drug wrote:
 16.11.2019 13:01, Avery Stupidman пишет:
 [...]
In general you shouldn't compare floating point values for equality because of their nature, you can use something like approxEqual https://dlang.org/library/std/math/approx_equal.html P.S. see also https://floating-point-gui.de/errors/comparison/
Yup, I'm dumb. Thank you very much for the help and the link. I should know better. Also apologies for the un-concise example.
Nov 16 2019
prev sibling parent berni44 <dlang d-ecke.de> writes:
On Saturday, 16 November 2019 at 10:01:25 UTC, Avery Stupidman 
wrote:
 assert(angleDeg(sqrt(3.0)/2.0, 1.5) == 60.0); // Fails
On my computer the results are very close, that is: import std.math: nextUp; assert(nextUp(angleDeg(sqrt(3.0)/2.0, 1.5)) == 60.0); // OK On Saturday, 16 November 2019 at 10:17:12 UTC, drug wrote:
 you can use something like approxEqual 
 https://dlang.org/library/std/math/approx_equal.html
With approxEqual, one needs to be very carefull. The default parameters allow for very odd results, accepting values to be equal, which are actually far apart considering the precision available; this is especially true, when using double or real. For example, here are about 12 significant fractional digits involved, which are completely ignored: assert(approxEqual(100.0,101.0)); // OK I wrote a replacement with better handling of the default parameters [1], but it looks like no one wants to take the burden to review it, probably because that would involve to make a decision. (Or maybe it has some other reasons I do not see.) [1] https://github.com/dlang/phobos/pull/7241
Nov 16 2019