C# 强制使浮点数的精确度相对较小

C# 强制使浮点数的精确度相对较小,c#,.net,mono,floating-point,C#,.net,Mono,Floating Point,我需要在浮点值中添加一个非常小的值,使其差异不大,从而使其无法通过相等性测试 为了避免精度问题,我选择添加一个相对较小的数字,而不是添加一个非常小的数字。这是一个好的解决方案吗?还是有可靠的方法来增加一个更小的数字 matrix.m00 += matrix.m00 * 0.0000001f; matrix.m11 += matrix.m11 * 0.0000001f; matrix.m22 += matrix.m22 * 0.0000001f; 通过阅读,我发现最好的解决方案是使用下一个可表示

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


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

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

通过阅读,我发现最好的解决方案是使用下一个可表示的浮点数。尽管在C#中,这样做的过程要么a)需要非托管/不安全的代码,要么b)使用速度太慢的
位转换器。因此,我认为上述解决方案会起作用,但我想知道是否有Gotchya。

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

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

您可以向任何double添加一个(取决于double);这是最小的数字,你可以添加或减去它,将改变其价值

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


可以添加到浮点数中的最小数是原始数的函数,而不是常数。调用此函数
Epsilon(x)

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

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


因此,除非您确定您的输入在某个固定的大小范围内(例如,所有值都接近0),否则您不能仅用一个常量来伪造它。

此库似乎有一个
增量
方法,可以满足您的需要:。确实如此。但OP本质上是问如何计算。你答案中的最后一个链接,我在搜索时确实遇到过,但我不明白。例如,为什么
u.i++
u.i--
在函数的末尾有什么不同吗?@Lea你知道C中的
联合是什么吗?这是试图“模拟”这一点。由于两个成员变量都是
FieldOffset(0)
,因此它们都指向内存中的同一点。封面下出现了某种指针别名。啊,那么
i
f
是在寻址相同的字段位吗?@Lea是的,基本上就是这样。感谢您指出0的情况,谢天谢地,0是唯一的无效值(即,它在我的代码中从来不是一个值)。我使用的平台不支持不安全的代码。@LeaHayes除了+0.0和-0.0之外,还有IEEE 754浮点数
n
,它们的属性是
n+n*0.0000001f==n
。从OP的问题(以及该问题中的代码)判断,他们已经意识到了这一点。“我选择增加一个相对较小的数字。我已经回答了第一个问题。
var big = 10000000000000000.0;
Console.WriteLine(big == (big + 1.0));