2013-03-06 74 views
1

我在浮点运算中有取消问题。我知道问题出在哪里,但我想不出一个有效的解决方案。用C++取消数值问题

这是我的问题:我有一个三维粒子模拟,所以每个粒子有3个坐标(x,y,z)。整个域被分割成子单元。在某一点上,我计算了粒子在某个时间步中的子单元的ID。这是一个简单的公式:

int cellOffset_y = (pos[1] - y_min)/cellWidth_y; 

POS [1]是颗粒的x坐标,是Y_MIN域和cellWidth一个单元的宽度的开始。

这里是我的问题:我有一个测试用例,在这种情况下,粒子的坐标应该为0。由于浮点不准确,它是大约。 -3E-18。当我使用这个公式时,-3e-18因取消而下降。现在最大的问题是,由于粒子位置是负的,并且边界恰好为0,所以我得到的返回的cellID不同于其中的粒子真正在其中。

因此,有没有人有一个想法如何解决这个问题?我希望这是明确提出

+2

难道你只是比较容忍? (如epsilon)。 – 111111 2013-03-06 19:49:54

+2

同样在你的片段中,'cellOffset_y'是一个int,e-18将只是0. – 111111 2013-03-06 19:51:55

+0

@ 111111:我认为它的'pos'是-3e-18 ... – 2013-03-06 19:53:22

回答

2

基本上有两种选择(当然,三,如果算上“住”的问题作为一个有效的选择!):

  1. Shift键的边框网格由少量,以便允许上游某种程度的不准确性。所以计算将变为(pos - y_min + k)/width,对于一些小值k

    当然,这并不能解决在另一个方向发生的错误(即数量稍大);事实上,这使情况变得更糟。但是没有解决这个问题的一般方法;你的代码不能“知道”-3e-18是正确的还是稍微错误的!

  2. 修复上游计算。

+0

1.得到了你提到的问题,它只会在一个方向上工作,上游计算基本上是给定的公式(我使用velocity-strömer-verlet算法)。第三种方法是在计算之后检查边界是否正确,但是这需要每个粒子额外的6次检查,并且我对性能感兴趣...... – Chris 2013-03-06 20:28:23

+0

@Chris:确实。所以这不是一个好的解决方案,除非你知道,例如,上游计算是有偏差的。 – 2013-03-06 20:29:20

+0

编辑我的上级评论 – Chris 2013-03-06 20:29:55