我有几个类遵循相同的基本概念来处理单位。
这是一个在单元测试中使用的简单示例:
[Test()]
public void Angle_MathOperatorTest()
{
Angle a1 = new Angle(AngleType.Degree, 360);
Angle a2 = new Angle(AngleType.Radian, Math.PI * 2);
Angle addedAngle = a1 + a2;
addedAngle.Degrees.ShouldBeEquivalentTo(720);
Angle subtractedAngle = a1 - a2;
subtractedAngle.Radians.ShouldBeEquivalentTo(0);
}
我已经制作了几个像这样演示的角度类的类,涵盖了其他基本单位类型。
向我揭示我遇到精度问题的特定类是使用处理长度单位的类:Dimension
我帮助构建了一个基本的几何库,利用这个 Dimension 类作为它的基本单元类型。例如,这是 Point 类:
public class Point
{
public Dimension X;
public Dimension Y;
public Dimension Z;
}
线和其他形状具有由使用此点类构建的维度和端点表示的长度等属性。
当我试图判断这些线是否全部平行时,问题就变得很明显了。在这个函数中:
/// <summary>
/// checks to see whether every line is parallel
/// </summary>
/// <param name="passedLines">passed List of Lines</param>
/// <returns></returns>
public static bool AreAllParallel(this List<Line> passedLines)
{
for (int i = 0; i < passedLines.Count - 1; i++)
{
if (!passedLines[i].IsParallelTo(passedLines[i + 1]))
{
return false;
}
}
return true;
}
它通常会返回 false,因为它检查的精度太高。在使用点和线进行旋转和平移之后,舍入加起来刚好足以使该函数在我希望它返回 true 时返回 false。
所以:
以下哪一组选择是正确/更好的选择?
- 只需检查
IsParallelTo
数字相对接近的功能(例如,在 0.0001 英寸内)
If(Math.Abs(thing.x - thing2.x) < .0001)
- 使用从配置文件中提取的变量常量改进了先前的想法,因此允许用户选择所需的可接受偏差
If(Math.Abs(thing.x - thing2.x) < Properties.AcceptedDeviationConstant)
- 或在维度类的根级别减少问题:
我可以使用相同的策略
//inside Dimension Equals
public override bool Equals(object obj)
{
return (Math.Abs(this.Inches - ((Dimension)(obj)).Inches)) < Constants.AcceptedEqualityDeviationConstant;
}
它真的看起来像这样,但上面更容易理解
return (Math.Abs(this.GetValue(this.InternalUnitType) - ((Dimension)(obj)).GetValue(this.InternalUnitType))) < Constants.AcceptedEqualityDeviationConstant;
或者最后,我的最后一个想法是将我的单位类中的所有内容替换为基本单位,Decimal
而不是Double
(维度、角度等)替换为十进制,并以某种方式(在研究之后)弄清楚这是否会有所帮助。
我应该如何以及在哪里提高班级平等运算的精度一致性?