如何做浮点比较?

如何做浮点比较?

我目前正在编写一些代码,其中有如下内容:

double a = SomeCalculation1();double b = SomeCalculation2();if (a < b)
    DoSomething2();else if (a > b)
    DoSomething3();

然后在其他地方,我可能需要做平等:

double a = SomeCalculation3();double b = SomeCalculation4();if (a == 0.0)
   DoSomethingUseful(1 / a);if (b == 0.0)
   return 0; // or something else here

总之,我有很多浮点的数学,我需要做各种条件的比较。我不能把它转换成整数数学,因为在这个上下文中,这样的事情是没有意义的。

我以前读过浮点比较可能是不可靠的,因为您可以这样做:

double a = 1.0 / 3.0;double b = a + a + a;if ((3 * a) != b)
    Console.WriteLine("Oh no!");

简而言之,我想知道:如何可靠地比较浮点数(小于,大于等于)?

我使用的数字范围大概在10e-14到10E6之间,所以我确实需要处理小数字和大数字。

我将此标记为语言不可知论者,因为无论我使用哪种语言,我都对如何实现这一目标感兴趣。


红糖糍粑
浏览 565回答 3
3回答

守着星空守着你

比较更大/更小并不是一个真正的问题,除非你在浮动/双精度限制的边缘工作。对于一个“模糊等于”的比较,这个(Java代码,应该很容易适应)是我想出来的浮点指南经过大量的工作,并考虑到了大量的批评:public&nbsp;static&nbsp;boolean&nbsp;nearlyEqual(float&nbsp;a,&nbsp;float&nbsp;b,&nbsp;float&nbsp;epsilon)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;float&nbsp;absA&nbsp;=&nbsp;Math.abs(a); &nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;float&nbsp;absB&nbsp;=&nbsp;Math.abs(b); &nbsp;&nbsp;&nbsp;&nbsp;final&nbsp;float&nbsp;diff&nbsp;=&nbsp;Math.abs(a&nbsp;-&nbsp;b); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(a&nbsp;==&nbsp;b)&nbsp;{&nbsp;//&nbsp;shortcut,&nbsp;handles&nbsp;infinities &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;if&nbsp;(a&nbsp;==&nbsp;0&nbsp;||&nbsp;b&nbsp;==&nbsp;0&nbsp;||&nbsp;diff&nbsp;<&nbsp;Float.MIN_NORMAL)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;a&nbsp;or&nbsp;b&nbsp;is&nbsp;zero&nbsp;or&nbsp;both&nbsp;are&nbsp;extremely&nbsp;close&nbsp;to&nbsp;it &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;relative&nbsp;error&nbsp;is&nbsp;less&nbsp;meaningful&nbsp;here &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;diff&nbsp;<&nbsp;(epsilon&nbsp;*&nbsp;Float.MIN_NORMAL); &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;//&nbsp;use&nbsp;relative&nbsp;error &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;diff&nbsp;/&nbsp;(absA&nbsp;+&nbsp;absB)&nbsp;<&nbsp;epsilon; &nbsp;&nbsp;&nbsp;&nbsp;}}它附带了一个测试套件。您应该立即排除任何没有的解决方案,因为在某些边缘情况下,几乎可以保证它会失败,比如有一个值0,两个与零相对的非常小的值,或者无穷大值。另一种选择(更多细节请参见上面的链接)是将浮点数的位模式转换为整数,并接受固定整数距离内的所有内容。在任何情况下,可能没有任何解决方案是完美的所有应用程序。理想情况下,您应该使用包含实际用例的测试套件来开发/调整自己的应用程序。

月关宝盒

我有个比较浮点数的问题A < B和A > B以下是似乎行之有效的方法:if(A&nbsp;-&nbsp;B&nbsp;<&nbsp;Epsilon)&nbsp;&&&nbsp;(fabs(A-B)&nbsp;>&nbsp;Epsilon){ &nbsp;&nbsp;&nbsp;&nbsp;printf("A&nbsp;is&nbsp;less&nbsp;than&nbsp;B");}if&nbsp;(A&nbsp;-&nbsp;B&nbsp;>&nbsp;Epsilon)&nbsp;&&&nbsp;(fabs(A-B)&nbsp;>&nbsp;Epsilon){ &nbsp;&nbsp;&nbsp;&nbsp;printf("A&nbsp;is&nbsp;greater&nbsp;than&nbsp;B");}晶圆厂-绝对值-照顾到它们是否本质上是平等的。

MM们

我们必须选择一个公差级别来比较浮点数。例如,final&nbsp;float&nbsp;TOLERANCE&nbsp;=&nbsp;0.00001;if&nbsp;(Math.abs(f1&nbsp;-&nbsp;f2)&nbsp;<&nbsp;TOLERANCE) &nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("Oh&nbsp;yes!");一个音符。你的例子很有趣。double&nbsp;a&nbsp;=&nbsp;1.0&nbsp;/&nbsp;3.0;double&nbsp;b&nbsp;=&nbsp;a&nbsp;+&nbsp;a&nbsp;+&nbsp;a;if&nbsp;(a&nbsp;!=&nbsp;b) &nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("Oh&nbsp;no!");这里有些数学a&nbsp;=&nbsp;1/3b&nbsp;=&nbsp;1/3&nbsp;+&nbsp;1/3&nbsp;+&nbsp;1/3&nbsp;=&nbsp;1.1/3&nbsp;!=&nbsp;1哦,是的.。你是说if&nbsp;(b&nbsp;!=&nbsp;1) &nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine("Oh&nbsp;no!")
打开App,查看更多内容
随时随地看视频慕课网APP