Java作业-从我的计算中得到一些奇怪的值

标签 java methods return coordinates trigonometry

我现在正在学习 Java,我的一项作业让我很困惑。我被要求创建一个类,它指定笛卡尔平面第一象限中的坐标,并且仅使用两个值来执行此操作:从所述点到原点 (0,0) 的距离以及 vector 绘制到原点的角度X 轴。到目前为止,程序看起来像这样:

public class Point2 {
    private double _radius;
    private double _alpha;

    public Point2 (int x, int y) {
        this._radius = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        this._alpha = Math.toDegrees(Math.atan2(y, x));
    }

    public Point2 (Point2 other) {
        this._radius = other._radius;
        this._alpha = other._alpha;
    }

    public int getX() {
        return (int)(this._radius * Math.cos(Math.toRadians(this._alpha)));
    }

    public int getY() {
        return (int)(this._radius * Math.sin(Math.toRadians(this._alpha)));
    }

    public void setX(int x) {
        if(x > 0) {
            this._radius = Math.sqrt(Math.pow(x, 2) + Math.pow(this.getY(), 2));
            this._alpha = Math.toDegrees(Math.atan2(this.getY(), x));
        }
    }

    public void setY(int y) {
        if(y > 0) {
            this._radius = Math.sqrt(Math.pow(this.getX(), 2) + Math.pow(y, 2));
            this._alpha = Math.toDegrees(Math.atan2(y, this.getX()));
        }
    }

    public boolean equals(Point2 other) {
        if(this._radius == other._radius && this._alpha == this._radius) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isAbove(Point2 other) {
        if(this.getY() > other.getY()) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isUnder(Point2 other) {
        if(this.getY() < other.getY()) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isLeft(Point2 other) {
        if(this.getX() < other.getX()) {
            return true;
        } else {
            return false;
        }
    }

    public boolean isRight(Point2 other) {
        if(this.getX() > other.getX()) {
            return true;
        } else {
            return false;
        }
    }

    double distance(Point2 other) {
        double dist = Math.sqrt(Math.pow(this.getX() - other.getX(), 2) + Math.pow(this.getY() - other.getY(), 2));

        return dist;
    }

    public void move(int dX, int dY) {
        if(this.getX() + dX > 0 && this.getY() + dY > 0) {
            this._radius = Math.sqrt(Math.pow(this.getX() + dX, 2) + Math.pow(this.getY() + dY, 2));
            this._alpha = Math.toDegrees(Math.atan2(this.getY() + dY, this.getX() + dX));
        }
    }

    public String toString() {
        return "(" + _radius + "," + _alpha + ")";
    }
}

无论如何,当我在给定 x 和 y 坐标的情况下创建此类的实例时,会发生什么,这确实没有问题——计算结果正确,一切都很好。问题是当我尝试使用任何更改 X 或 Y 坐标的方法时。

例如,我将运行 setX(10),当我运行 getX() 时,我会得到 9,但是当我运行 再次 setX(10) ,然后重新运行 get(X),我会得到 10。 move() 也是如此 - 一旦返回就调用该方法getX()getY() 的结果不准确,但使用相同参数调用该方法一次或两次将更正结果。

这很奇怪 - 几乎就像这里的计算不正确或者存在舍入问题。有人知道吗?

最佳答案

您肯定遇到了舍入错误。解决这个问题的第一种方法是直接存储 x 和 y。一般来说,存储计算数据是一个坏主意。但是,我假设这是不可能的。

您遇到了两个问题。

在此代码中:

this._radius = Math.sqrt(Math.pow(x, 2) + Math.pow(this.getY(), 2));
this._alpha = Math.toDegrees(Math.atan2(this.getY(), x));

请注意,this.getY() 取决于半径和 alpha。当您在第一次调用中更改半径时,您从 getY 获得的值在第二次调用中将有所不同!您想要缓存从 getY 返回的值:

int y = this.getY();
this._radius = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
this._alpha = Math.toDegrees(Math.atan2(y, x));

在 setY 中也发现了同样的问题,其中 getX 改变了中间函数。

您遇到的另一个问题是由于在 getX/getY 中将 double 型转换为整数所致。 Java 通过截断来实现这一点:(int) 4.99999999 将变为 4。使用 (int) Math.round(...) 可能会获得更好的结果(如果传递 double,Math.round() 将返回 long)。

结论

  • 如果可能,请更改代码以直接存储 x 和 y,您可以根据这些值计算角度和半径。
  • 考虑 x 和 y 可能是非整数。为什么要将它们限制为整数?
  • 请注意,在修改对象的过程中,对象的状态可能不一致,例如当您仅根据新的 x 值修改半径时,调用 getY 是不安全的。

关于Java作业-从我的计算中得到一些奇怪的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29725782/

相关文章:

java - 如何将多个小整数保存在一个整数中以进行位移位?

java - 转换 Java 对象的最佳实践/模式

java - 如何通过轮询检索新传入的数据并将其反馈回来

java - 比较两个数组,增加计数器

c++ - 将char数组存储在一个类中然后返回它

ios - for循环Swift iOS的退出迭代

java - Akka 和 Play,与非 Controller 库集成

java - Robolectric 测试中 Android Activity 中的模拟字段

java - 无法执行 cd/usr/bin/java

java - 每次创建新客户对象时创建唯一的客户ID。这可能吗? java