F# - 如何比较浮点数

3

在 F# 中,如何高效地比较几乎相等的浮点数?它应该适用于非常大和非常小的值。我考虑先比较指数,然后比较尾数(有效数字),同时忽略其 52 位中的最后 4 位。这是一个好方法吗?我如何获取浮点数的指数和尾数(有效数字)?


1
зұ»дјјдәҺ abs(a-b)<threshold жҲ– abs(a-b)<threshold*a иҝҷж ·зҡ„д»Јз Ғжңүд»Җд№Ҳй—®йўҳе‘ўпјҹеңЁ F# дёӯиҺ·еҸ–жө®зӮ№ж•°зҡ„дҪҚеҸҜиғҪдјҡжҜ”жү§иЎҢиҝҷдёӨдёӘж“ҚдҪңзҡ„ејҖй”ҖжӣҙеӨ§пјҢеӣ дёәе®ғйңҖиҰҒеҲҶй…ҚдёҖдёӘеӯ—иҠӮж•°з»„гҖӮ - John Palmer
谢谢@JohnPalmer,你的第二个建议abs(a-b)<threshold*abs(a)(加上一个额外的abs())正是我想要的。一个相对阈值。 - Goswin Rothenthal
讨论 https://dev59.com/P3VD5IYBdhLWcg3wU5-H#77735 可以帮助您选择规则,尽管它不涵盖在 F# 中编写该规则的内容。 - Ben Voigt
2个回答

3
一个F#的float只是一个System.Double的简写。因此,您可以使用BitConverter.DoubleToInt64Bits方法高效(而且安全!)地将F# float值“转换”为int64;这很有用,因为它避免了分配byte[],就像John在他的评论中提到的那样。您可以使用一些简单的位运算从该int64中获取指数和有效数字。
不过正如John所说,您可能更适合使用简单的相对精度检查。这可能是最快的解决方案,并且对于许多用例(例如,检查迭代求解器是否已收敛于解)足够接近。如果您需要特定的准确度,请查看NUnit的代码--它具有一些很好的API,可断言值是否在预期值的某个百分比或ulps数量内。

3
当你询问如何比较几乎相等的浮点数值时,实际上是在问:
我有两个使用浮点运算计算得来的值x和y,它们包含舍入误差,并且是理想数学值x和y的近似值。 我如何使用浮点数值x和y来比较数学值x和y是否相等?
这里涉及两个问题:
我们不知道x或y中可能存在多少误差。 某些算术组合会放大误差,而其他组合会缩小误差。 x和y中的误差可能从零到无穷大,而您没有给出任何有关此信息的信息。
通常假定目标是产生“相等”的结果,即使当x和y不相等但彼此接近的情况下也是如此。 这将错误的负面影响转换为积极影响(即使数学x和y不相等,也会报告不等),但是会导致错误的积极影响(即使数学x和y不相等也会报告相等)。
因此,对于已近似计算的值,在一般情况下不存在正确的相等性测试方法。
请注意,这个问题并不是真正意义上的相等性测试。 通常情况下,无法计算不正确数据的任何功能(除了诸如常数函数之类的微不足道的函数)。 由于x和y包含错误,因此无法使用x计算log(x)或计算arcosine(y)或sqrt(x)而不产生误差。 实际上,如果误差使得y略大于1,而y不是,或者使得x略小于零,而x不是,则计算acos(y)或sqrt(x)将产生异常和NaN,即使理想数学值没有问题。
这个意思是说,你不能简单地将数学运算转换为近似的浮点运算,然后期望得到好的结果(无论你是否测试相等)。你必须考虑将精确运算转换为近似运算的影响,并评估它们如何影响你的程序和数据。使用浮点运算,包括相等比较,必须根据不同情况进行适当调整。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接