【问题标题】:Quaternion Comparison?四元数比较?
【发布时间】:2011-04-27 11:52:59
【问题描述】:

可以进行四元数比较吗?我正在编写一个四元数的 Java 类,我想实现 Comparable 接口以使用 Collections.sort(List<Quaternion>) 设施。我不是数学专家,我真的不明白我读到的关于四元数的东西。那么,谁能告诉我我可以覆盖四元数的compareTo 方法吗?

我的班级宣言:

public class Quaternion implements Serializable, Comparable<Quaternion> {

    private double s; // scalar part
    private double i, j, k; // vectorel part


    public Quaternion() {
        super();
    }

    public Quaternion(double s, double i, double j, double k) {
        super();
        this.s = s;
        this.i = i;
        this.j = j;
        this.k = k;
    }

【问题讨论】:

  • 这是一道数学题,不是编程题。询问数学专家,如果您在实施该解决方案时遇到问题,请在此处寻求实施帮助。

标签: java math comparison comparable quaternions


【解决方案1】:

您可以通过比较其字段来实现 compareTo。但是,您需要确定您希望订单是什么样的。 AFAIK,对于复数之前或之后的内容没有标准定义,更不用说四元数了。

【讨论】:

    【解决方案2】:

    你当然可以比较它们;比较是否有意义还有待商榷。由于四元数可以用四个实数表示,因此您只需执行(伪代码)之类的操作

    if (q1.a != q2.a)
        return q1.a - q2.a;
    else if (q1.b != q2.b)
        return q1.b - q2.b;
    else if (q1.c != q2.c)
        return q1.c - q2.c;
    else
        return q1.d - q2.d;
    

    由于值是实数,您可能会使用基于 epsilon 的比较,并且您需要将小的正负差转换为正整数和负整数。但你明白了。

    【讨论】:

      【解决方案3】:

      没有理由不能比较两个四元数。假设您要比较幅度,计算并比较Quaternion Norms。您的四元数类应该有一个规范(幅度)方法,允许 toCompare 类似于以下内容:

      int compareTo(Quaternion o){
        return (int)(this.norm() - o.norm());
      }
      

      更好的版本是:

      int compareTo(Quaternion o){
        // return (int)(this.norm() - o.norm());
        double tNorm = this.norm;
        double oNorm = o.norm;
        int retVal = 0;
      
        if (tNorm < oNorm){
          retVal = -1;
        } else if (tNorm > oNorm){
          retVal = 1;
        }
      
        return retVal;
      }
      

      【讨论】:

      • 我建议不要在compareTo 中使用-(因为可能会溢出)。使用&lt; 或委托给Integer.compareTo
      • 是的,我已经实现了 norm 方法,这似乎是最有意义的比较。谢谢
      • 你不应该比较四元数是有原因的:它们不能被排序。您可以定义如何比较两个四元数,但也有一些缺点。使用范数时最严重的是(正如 Klas 提到的)两个不相等的四元数可以有相等的范数。这也违反了definition of the compareTo-method,它规定只有当两个对象相等时它才应该返回 0。
      • @martin:你不在数学中比较四元数的真正原因是你不能有 (a a + c 0 and b > 0 => ab > 0) 因为这意味着 -1 0。这些公理需要对排序做任何有意义的事情。在树中存储四元数时,字典顺序非常好。但是我同意按规范进行比较是愚蠢的,因为它会默默地破坏许多依赖于 (not(a b) => a == b) 的算法。
      • -1 您的排序与equals不一致,不推荐用于Comparable接口的实现。
      【解决方案4】:

      四元数是一种 4 维向量。 你想如何订购它们?最合理的方法是使用规范。

      public int compareTo(Object o) {
        if (o instanceOf Quaternion) {
          // Compute the difference between the square of the norm
          double result = s*s + i*i + j*j + k*k - o.s*o.s - o.i*o.i - o.j*o.j - o.k*o.k;
          if (result > 0) { return 1; }
          if (result < 0) { return -1; }
          return 0;
        }
      }
      

      请注意,使用范数会使长度相等但指向不同方向的四元数相等,并且某些算法将无法区分它们。排序算法很可能会丢弃“重复项”。只是一个友好的警告。

      【讨论】:

        【解决方案5】:

        将四元数视为四个浮点数的元组(有序列表)。定义相等性非常简单,但是您将如何定义总顺序?换句话说,你想如何定义两个四数序列之间的大于关系?

        事实上,即使是复数之间也没有共同的大于关系,四元数可以被认为是一对复数。简单的比较只能在一维空间中进行。复数是二维的,四元数 - 四个。

        【讨论】:

          【解决方案6】:

          你可以,但我认为你不应该。

          参数与复数相同。给定两个四元数,它们要么相等,要么不相等,没有办法说哪个大于另一个。四元数形成一个除法代数,它是无序的(不像实数的领域)。我能想到的唯一(合理)方法是使用范数来比较两个四元数。

          double norm = Math.sqrt(s*s + i*i + j*j + k*k);
          

          在这种情况下,您可以定义,即四元数 a 大于四元数 b 如果 a 大于 b 的范数。但这绝对不是一个标准定义。我会小心地使四元数或复数具有可比性。但是,这取决于您的用例。请注意,没有对此类数字进行排序的标准方法。

          查看这个google search 以获得一些关于比较复数的好链接。四元数的论证基本相同。

          比较四元数的另一种方法是使用lexicographic order

          【讨论】:

          • 论点很简单。我们这里不需要的有序环公理 (en.wikipedia.org/wiki/Ordered_ring) 暗示如果 i > 0,i * i > 0,所以 -1 > 0。但是 1 > 0,因为 1 = 1 * 1 因此 0 > -1(通过在两侧添加 -1)。另请注意,如果 -1 不是平方和,则对字段进行排序。
          【解决方案7】:

          四元数或复数没有数学标准排序。

          您可能仍然希望实现Comparable 接口,以便方便地对它们进行排序并将它们存储在TreeSetTreeMap 集合中。

          为了明确排序是任意的,我将使用四元数组件的字典组合。这也确保了排序与equals 一致,并且算法按预期工作。

          对于更自然的排序,例如考虑规范的排序,您始终可以显式定义一个比较器。

          【讨论】:

          • 请记住,如果您想在该树中查找一个四元值,并且它与树中已有的不完全匹配,您很容易在一个叶节点旁边结束不是“最接近”的值(通过距离度量)。很容易有一个叶子节点,它通过距离度量更接近,但在词汇排序顺序上却有一些距离。所以它提出了如何使用结构的问题,因为浮点计算总是有一些“模糊”......
          • 一旦你有两个或更多维度,你就无法避免这种情况。您可以做的最好的事情是相反,这样在您的排序中接近的值在空间中也接近,通过一些空间归档曲线。例如,在二维空间中的应用是先按与某个选定点的距离排序,然后按字典顺序打破关系(“给我找一家靠近 P 的酒店”)。
          猜你喜欢
          • 1970-01-01
          • 2020-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-22
          • 2016-03-25
          • 2017-01-27
          相关资源
          最近更新 更多