C#的浮点比较函数

C#的浮点比较函数

有人可以在C#中指向(或显示)一些好的通用浮点比较函数来比较浮点值吗?我想实现的功能IsEqualIsGreater一个IsLess。我也只关心双打不漂浮。



扬帆大鱼
浏览 1105回答 3
3回答

白板的微信

编写一个有用的通用浮点IsEqual是非常非常困难的,如果不是完全不可能的话。您当前的代码将严重失败a==0。该方法应该如何处理这种情况实际上是一个定义的问题,并且可以说代码最适合特定的域用例。对于这种事情,你真的需要一个好的测试套件。这就是我为浮点指南做的,这就是我最终提出的(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;absA&nbsp;+&nbsp;absB&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;}}您还可以在网站上找到测试套件。附录:&nbsp;c#中的相同代码用于双打(在问题中提到)public&nbsp;static&nbsp;bool&nbsp;NearlyEqual(double&nbsp;a,&nbsp;double&nbsp;b,&nbsp;double&nbsp;epsilon){ &nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;double&nbsp;MinNormal&nbsp;=&nbsp;2.2250738585072014E-308d; &nbsp;&nbsp;&nbsp;&nbsp;double&nbsp;absA&nbsp;=&nbsp;Math.Abs(a); &nbsp;&nbsp;&nbsp;&nbsp;double&nbsp;absB&nbsp;=&nbsp;Math.Abs(b); &nbsp;&nbsp;&nbsp;&nbsp;double&nbsp;diff&nbsp;=&nbsp;Math.Abs(a&nbsp;-&nbsp;b); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(a.Equals(b)) &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;//&nbsp;shortcut,&nbsp;handles&nbsp;infinities &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;else&nbsp;if&nbsp;(a&nbsp;==&nbsp;0&nbsp;||&nbsp;b&nbsp;==&nbsp;0&nbsp;||&nbsp;absA&nbsp;+&nbsp;absB&nbsp;<&nbsp;MinNormal)&nbsp; &nbsp;&nbsp;&nbsp;&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;MinNormal); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;else &nbsp;&nbsp;&nbsp;&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;}}

largeQ

从Bruce Dawson关于比较浮点数的论文中,您还可以将浮点数作为整数进行比较。接近度由最低有效位确定。public&nbsp;static&nbsp;bool&nbsp;AlmostEqual2sComplement(&nbsp;float&nbsp;a,&nbsp;float&nbsp;b,&nbsp;int&nbsp;maxDeltaBits&nbsp;)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;aInt&nbsp;=&nbsp;BitConverter.ToInt32(&nbsp;BitConverter.GetBytes(&nbsp;a&nbsp;),&nbsp;0&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(&nbsp;aInt&nbsp;<&nbsp;&nbsp;0&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aInt&nbsp;=&nbsp;Int32.MinValue&nbsp;-&nbsp;aInt;&nbsp;&nbsp;//&nbsp;Int32.MinValue&nbsp;=&nbsp;0x80000000 &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;bInt&nbsp;=&nbsp;BitConverter.ToInt32(&nbsp;BitConverter.GetBytes(&nbsp;b&nbsp;),&nbsp;0&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(&nbsp;bInt&nbsp;<&nbsp;0&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bInt&nbsp;=&nbsp;Int32.MinValue&nbsp;-&nbsp;bInt; &nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;intDiff&nbsp;=&nbsp;Math.Abs(&nbsp;aInt&nbsp;-&nbsp;bInt&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;intDiff&nbsp;<=&nbsp;(&nbsp;1&nbsp;<<&nbsp;maxDeltaBits&nbsp;);}编辑:BitConverter相对较慢。如果您愿意使用不安全的代码,那么这是一个非常快的版本:&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;unsafe&nbsp;int&nbsp;FloatToInt32Bits(&nbsp;float&nbsp;f&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;*(&nbsp;(int*)&f&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;bool&nbsp;AlmostEqual2sComplement(&nbsp;float&nbsp;a,&nbsp;float&nbsp;b,&nbsp;int&nbsp;maxDeltaBits&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;aInt&nbsp;=&nbsp;FloatToInt32Bits(&nbsp;a&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(&nbsp;aInt&nbsp;<&nbsp;0&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aInt&nbsp;=&nbsp;Int32.MinValue&nbsp;-&nbsp;aInt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;bInt&nbsp;=&nbsp;FloatToInt32Bits(&nbsp;b&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(&nbsp;bInt&nbsp;<&nbsp;0&nbsp;) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bInt&nbsp;=&nbsp;Int32.MinValue&nbsp;-&nbsp;bInt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;intDiff&nbsp;=&nbsp;Math.Abs(&nbsp;aInt&nbsp;-&nbsp;bInt&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;intDiff&nbsp;<=&nbsp;(&nbsp;1&nbsp;<<&nbsp;maxDeltaBits&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;}

幕布斯7119047

继Andrew Wang的回答:如果BitConverter方法太慢但你不能在你的项目中使用不安全的代码,这个结构比BitConverter快6倍:[StructLayout(LayoutKind.Explicit)]public&nbsp;struct&nbsp;FloatToIntSafeBitConverter{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;int&nbsp;Convert(float&nbsp;value) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;FloatToIntSafeBitConverter(value).IntValue; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;FloatToIntSafeBitConverter(float&nbsp;floatValue):&nbsp;this() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FloatValue&nbsp;=&nbsp;floatValue; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[FieldOffset(0)] &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;readonly&nbsp;int&nbsp;IntValue; &nbsp;&nbsp;&nbsp;&nbsp;[FieldOffset(0)] &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;readonly&nbsp;float&nbsp;FloatValue;}(顺便说一句,我尝试使用已接受的解决方案,但它(至少我的转换)失败了一些在答案中也提到的单元测试。例如assertTrue(nearlyEqual(Float.MIN_VALUE, -Float.MIN_VALUE));)
打开App,查看更多内容
随时随地看视频慕课网APP