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

本文关键字:不准确 准确度 相对 浮点数 | 更新日期: 2023-09-27 18:00:34

我需要在浮点值上添加一个非常小的值,使其差异不大,从而使其无法通过相等测试。

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

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

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

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

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

  • 计算双打最后一位的单位(ULP)
  • 下一个更高/更低的IEEE双精度数字

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

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

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

你为什么不能使用不安全的代码来做这件事?

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

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

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

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

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