c# - 如何解决精度问题

标签 c# decimal precision unit-class-library geometry-class-library

<分区>

我有几个类在处理单位时遵循相同的基本概念。

这是一个在单元测试中使用的简单示例:

    [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);
    }

我已经制作了几个这样的类来演示Angle Class,涵盖了其他基本单位类型。

向我揭示我遇到精度问题的特定类是使用处理长度单位的类: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 等函数中检查数字是否相对接近(例如在 .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;
}

确实看起来像这样但是上面的更容易理解

返回 (Math.Abs​​(this.GetValue(this.InternalUnitType) - ((Dimension)(obj)).GetValue(this.InternalUnitType))) < Constants.AcceptedEqualityDeviationConstant;

或者最后,我最后的想法是将我的单位类中的所有内容替换为 Decimal 的基本单位,而不是 Double(尺寸、角度等)到 Decimal并以某种方式(在研究之后)弄清楚这是否有帮助。


我应该如何以及在何处提高类相等操作的精度一致性?

附注这些库是开源的,可以找到(单位 here 和几何 here)

最佳答案

如果 e1 是第一条线的方向,e2 是第二条线的方向,则检查它们是否在 θ(弧度)的斜率公差内平行,执行以下操作以下(伪代码):

bool is_parallel = |Cross(e1,e2)| <= |e1|*|e2|*Cos(θ)

其中 |v| 是矢量幅度,Cross() 是矢量叉积。

关于c# - 如何解决精度问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26185211/

相关文章:

c# - 使用 C# Reactive Extensions 在特定时间调用函数

c++ - 来自整数和无效操作数的小数 *更新

C# 进程等待毫秒精确

javascript - 下载 c# excel 字节数组并将其转换为 javascript blob

数组元素逐元素差异的C#方法(导数近似)?

c# - 如何实现 IEqualityComparer 以返回不同的值?

postgresql - 为什么我的 PostgreSQL 随机数右填充零?

Java 更改应用程序

c++ - 如何优化从半精度 float16 到单精度 float32 的转换?

sqlite - CoreData NSDate SQLite 精度差异