c# - 传播更改时如何提高数值稳定性
问题描述
我正在尝试沿数字列表传播更改的值。
变化很小,但列表中的值可能很大。
这会导致一些我想防止的数值不稳定。
例子:
public class Polyline
{
private List<Vector3> points = new List<Vector3>();
// For every point in points, contains the total polyline length
// from the first point up to this point.
private List<double> distances = new List<double>({0.0});
[...]
public void Insert(int index, Vector3 point)
{
points.Insert(index, point);
if (points.Count >= 2)
{
double change;
if (index == 0)
{
// Point gets inserted at the start of the polyline
distances.Insert(0, 0f);
change = VectorMath.PreciseDistance(points[1], point);
}
else if (index == points.Count - 1)
{
// Point gets inserted at the end of the polyline
change = 0.0;
var length = VectorMath.PreciseDistance(point, points[index - 1]);
var prevLength = distances[distances.Count - 1];
distances.Add(prevLength + length);
}
else
{
// Point gets added somewhere inside the polyline
var prev = points[index - 1];
var next = points[index + 1];
var prevLength = distances[index - 1];
// Get the edge lengths of the resulting triangle (prev, point, next)
var l0 = VectorMath.PreciseDistance(point, prev);
var l1 = VectorMath.PreciseDistance(next, point);
var lOld = distances[index] - prevLength;
distances.Insert(index, prevLength + l0);
change = l0 + l1 - lOld;
}
// Propagate the distance change along subsequent distances
for (var i = index + 1; i < distances.Count; i++)
{
distances[i] += change;
}
}
}
}
public static class VectorMath
{
// Calculates the distance as precise as possible
public static double PreciseDistance(Vector3 a, Vector3 b)
{
var x = (double) (a.x) - b.x;
var y = (double) (a.y) - b.y;
var z = (double) (a.z) - b.z;
return Math.Sqrt(x * x + y * y + z * z);
}
}
在这个例子中,我有一个折线类,它存储它的点,还有一个距离列表。
这些距离表示折线到同一索引处的点的长度。
当折线很长时,插入会导致数值不稳定。
尤其是后面的条目,总长度很大,不精确性变得很大。
问题:
如何更改代码/系统,以便我仍然可以找到给定索引的总长度,而不必担心数值不稳定。
找到该长度应该很快,因此每次需要重新计算它是不可行的。
假设变化值足够精确。
另外我想防止使用双精度或小数,因为性能是一个大问题。
背景:
我的问题实际上是折线类。
如果可能的话,我想使用浮点精度来保持距离,因为框架的其余部分也使用浮点数。
了解不稳定性:
给定随机插入的 1000 个点,总长度约为 5000 个单位。
实际长度与最后一个距离条目中存储的总长度之差约为+-0.2f。
注意:
在原始帖子中,我使用浮点数来表示距离。
正如@derHugo 正确指出的那样,浮点数的精度约为 6-9 位,因此该错误是意料之中的。
但是,将所有内容更改为 double 后(除了 Vector3 -> Unity 类),数值误差仅减少了大约一位数。
因此问题仍然存在。
我添加了Insert的完整源代码,也许我那里有错误......
解决方案
推荐阅读
- python - 从两个矩阵的比较中创建新矩阵
- jquery - 仅当内部最后一个 li 具有 .active 时才添加下一个按钮新类
- javascript - 如何将星级值保存到本地存储以及页面重新加载时如何显示?
- javascript - 单击 Windows 任务栏的固定图标时,将重定向到“chrome://extensions”而不是打开应用程序窗口
- python - 是否可以使用 Django 和 web3.js 构建 DApp?
- amazon-web-services - Terraform 覆盖 AWS 托管策略
- android - Android 将音频/mp3 文件保存到外部存储
- html - 为绝对位置元素应用相对位置。(相对于子 div)
- botframework - 使用 Microsoft BotFramework SDK 的限制是什么?
- nashorn - Nashorn javascript引擎-java8中的加法运算