2

我需要将一个非常小的值添加到浮点值以使其差异微不足道,从而使其无法通过相等性测试。

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

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

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

4

3 回答 3

3

您可以将ulp添加到任何双精度数(取决于双精度数);这是您可以添加或减去的最小数字,它会改变它的值。

不过,这些帖子都使用BitConverter. 我发现了一篇讨论如何在没有不安全代码的情况下添加 ulp 的帖子BitConverter,但是:

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

于 2013-02-23T01:28:29.380 回答
1

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

你有什么理由不能使用不安全的代码来做到这一点?

于 2013-02-23T01:26:10.883 回答
1

您可以添加到浮点数以产生不同数字的最小数字是原始数字的函数,它不是某个常数。调用这个函数Epsilon(x)

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

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

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

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

于 2013-02-23T01:41:08.920 回答