强制浮点数的相对较小的不准确性

时间:2013-02-23 01:21:37

标签: c# .net mono floating-point

我需要在浮点值上添加一个非常小的值,使其微不足道,以便它无法通过相等测试。

为了避免精确度问题,我选择添加一个相对较小的数字,而不是添加一个非常小的数字。这是一个好的解决方案吗?或者是否有可靠的方法来添加更小的数字?

matrix.m00 += matrix.m00 * 0.0000001f;
matrix.m11 += matrix.m11 * 0.0000001f;
matrix.m22 += matrix.m22 * 0.0000001f;

从阅读中我发现最好的解决方案是使用下一个可表示的浮点数。虽然在C#中执行此操作的过程要么a)需要非托管/不安全代码,要么b)使用速度太慢的BitConverter。所以我认为上述解决方案可行,但我想知道是否有任何问题。

3 个答案:

答案 0 :(得分:3)

您可以为任意双倍添加ulp(取决于双倍);这是您可以添加或减去的最小数字,它将改变其值。

但是,这些帖子都使用BitConverter。我发现了一篇文章讨论了如何添加没有不安全代码的ulp或BitConverter,但是:

http://realtimemadness.blogspot.com/2012/06/nextafter-in-c-without-allocations-of.html

答案 1 :(得分:1)

当然有一个问题。如果这些值中的任何一个为0,那么您将正好添加0,即根本不修改该值。

有什么理由不能使用不安全的代码来执行此操作吗?

答案 2 :(得分:1)

您可以添加到浮点数的最小数量,以便生成不同的数字是原始数字的函数,它不是一些常数。调用此函数Epsilon(x)

Epsilon(0),即可以添加到浮点0的最小浮点数,以便生成可区分的数字,可以在静态值Double.Epsilon中找到。

尽管使用像1这样的“大”epsilon最终会失败。例如,这在C#中返回true:

var big = 10000000000000000.0;
Console.WriteLine(big == (big + 1.0));

因此,除非您确定您的输入处于某个固定的幅度范围内(例如全部接近0),否则您不能只用一个常数来捏造它。