在.NET中使用浮点错误处理浮点、错误、NET

2023-09-03 05:02:37 作者:闭眼入你梦

我工作的一个科学计算和放大器;可视化项目在C#/。NET,我们使用 s至重新present所有的物理量。因为浮点数始终包括位四舍五入,我们有简单的方法做相等比较,如:

I'm working on a scientific computation & visualization project in C#/.NET, and we use doubles to represent all the physical quantities. Since floating-point numbers always include a bit of rounding, we have simple methods to do equality comparisons, such as:

static double EPSILON = 1e-6;

bool ApproxEquals(double d1, double d2) {
    return Math.Abs(d1 - d2) < EPSILON;
}

pretty的标准。

Pretty standard.

不过,我们不断发现自己不得不调整 EPSILON幅度我们所遇到的情况,即平等数量的误差大于我们的预期。例如,如果你乘5大取值在一起,然后除以5次,你失去了很多的准确性。它得到的地步,我们不能让EPSILON太多大,否则这将会给我们误报,但我们仍然得到假阴性为好。

However, we constantly find ourselves having to adjust the magnitude of EPSILON as we encounter situations in which the error of "equal" quantities is greater than we had anticipated. For example, if you multiply 5 large doubles together and then divide 5 times, you lose a lot of accuracy. It's gotten to the point where we can't make EPSILON too much larger or else it's going to give us false positives, but we still get false negatives as well.

在我们的一般方法是寻找更多的数值稳定算法的工作,但程序非常的计算和只有这么多,我们已经能够做到。

In general our approach has been to look for more numerically-stable algorithms to work with, but the program is very computational and there's only so much we've been able to do.

有没有人有处理这个问题有什么好的策略?我进去看了十进制键入了一点,但我担心的表现,我真的不知道有足够的了解才知道它是否会解决这个问题,或者只晦涩它。我愿意接受适度的性能损失(比如2倍)转到十进制是否会解决这些问题,但性能绝对是一个关注并自code主要是受限于浮点运算,我不认为这是不合理的问题。我见过的人引用了100倍的差异,这肯定是不能接受的。

Does anyone have any good strategies for dealing with this problem? I've looked into the Decimal type a bit, but am concerned about performance and I don't really know enough about it to know if it would solve the problem or only obscure it. I would be willing to accept a moderate performance hit (say, 2x) by going to Decimal if it would fix these problems, but performance is definitely a concern and since the code is mostly limited by floating-point arithmetic, I don't think it's an unreasonable concern. I've seen people quoting a 100x difference, which would definitely be unacceptable.

此外,切换到十进制有其他并发症,如普遍缺乏支持,在数学库,所以我们必须写我们自己的平方根函数,例如。

Also, switching to Decimal has other complications, such as general lack of support in the Math library, so we would have to write our own square root function, for example.

任何意见?

编辑:顺便说一句,我使用恒定小量(而不是相对比较)其实不是我的问题点。我只是把有作为一个例子,这不是真正的我的code一的这段。更改为一个相对的比较不会做出对这个问题有区别的​​,因为问题出现了失去precision时数得到非常大的,然后小了。例如,我可能有一个值1000,然后我做了一系列的计算上,应该导致完全一样的数字,但由于precision亏我居然有1001如果我然后去比较这些数字,也没有多大意义,如果我用一个相对或绝对的比较(只要我定义的比较的方式,是有意义的问题和规模)。

by the way, the fact that I'm using a constant epsilon (instead of a relative comparison) is not the point of my question. I just put that there as an example, it's not actually a snippit of my code. Changing to a relative comparison wouldn't make a difference for the question, because the problem arises from losing precision when numbers get very big and then small again. For example, I might have a value 1000 and then I do a series of calculations on it that should result in exactly the same number, but due to loss of precision I actually have 1001. If I then go to compare those numbers, it doesn't matter much if I use a relative or absolute comparison (as long as I've defined the comparisons in a way that are meaningful to the problem and scale).

总之,作为米奇小麦建议,算法重新排序并帮助的问题。

Anyway, as Mitch Wheat suggested, reordering of the algorithms did help with the problems.

推荐答案

这是不是一个问题,唯一的.NET。减少precision损失的策略是重新排序计算,这样你乘小批量,大批量倍,加/减similiar大小的数量(不改变计算的本质,很明显)。

This is not a problem unique to .NET. The strategy to reduce loss of precision is to re-order calculations so that you multiply large quantities times small quantities and add/subtract similiar sized quantities (without changing the nature of the calculation, obviously).

在你的榜样,而不是乘5大批量在一起,然后通过5大批量的划分,再以将每个大量的除数中的一个,然后乘这5个部分结果。

In your example, rather than multiply 5 large quantities together and then divide by 5 large quantities, re-order to divide each large quantity by one of the divisors, and then multiply these 5 partial results.

感兴趣的? (如果你还没有读):什么每台计算机科学家应该知道关于浮点浮点运算

Of interest? (if you haven't already read): What Every Computer Scientist Should Know About Floating-Point Arithmetic