5

I'm trying to check to see if a triangle is a right triangle in Java. This is a portion of what the tester class does:

    Triangle a = new Triangle(new Point(2, 2), new Point(6, 2), new Point(2, 6) );
    System.out.println(a.isRight()); //Expects True

A portion of my triangle class receives the values and sets them to x1,y2 etc:

    public Triangle(Point loc1, Point loc2, Point loc3) {
    x1 =  loc1.getX(); y1 =  loc1.getY();
    . . .

The first two segments of code were given to me. I am to make the last segment of code which I made to be this:

    public boolean isRight() {
        if((Math.pow(side1,2)+Math.pow(side2,2)) == Math.pow(side3,2))
            return true;
        if((Math.pow(side2,2)+Math.pow(side1,2)) == Math.pow(side3,2))
            return true;
        if((Math.pow(side3,2)+Math.pow(side2,2)) == Math.pow(side1,2))
            return true;
        else
            return false;
    }

However, it still returns false. What am I doing wrong? Thanks a bunch!

Update: Thanks for the help. I seem to have made a rather noob-ish mistake. I never thought about the fact that doubles weren't really accurate (sorry, just trying to say what I did in simple terms). I ended up inputting this:

        if(Math.abs(side1*side1 + side2*side2 - side3*side3) < 0.2)
        return true;
    if(Math.abs(side1*side1 + side3*side3 - side2*side2) < 0.2)
        return true;
    if(Math.abs(side3*side3 + side2*side2 - side1*side1) < 0.2)
        return true;
    else
        return false;

Once again, thanks for the help!

Frankmeister
  • 61
  • 1
  • 1
  • 4
  • 2
    Just an FYI: titles like _"Can someone help me find the error in my java code?"_ are discouraged. You should try and make the title something more specific to your problem. Something like _"Checking if a triangle is a right triangle"_ would be more appropriate. For one it helps searches, as post are for all to discover. – Paul Samsotha Dec 19 '14 at 05:55
  • Okay, thank you. This is actually my first post. – Frankmeister Dec 19 '14 at 10:52

5 Answers5

6

I see a number of problems:

  • you check both a2 + b2 = c2 and b2 + a2 = c2, but these are actually equivalent
  • you never check if a2 + c2 = b2.
  • you use Math.pow to square a number, which is both inefficient and imprecise. (You should just use *.)
  • you expect floating-point arithmetic to give an exact value — suitable for == — which it generally does not.
ruakh
  • 175,680
  • 26
  • 273
  • 307
  • As a purely academic question: How does Math.pow work if not an incremental `*`? – Sinkingpoint Dec 19 '14 at 05:20
  • 1
    @Quirliom: Both arguments of `Math.pow` are `double`-s, so repeated multiplication would not work. (What repeated multiplication could compute `Math.pow(3.2, 3.2)`?) There are a lot of special cases, but in the most common case, `Math.pow(x,y)` is exp(*y* ln *x*). – ruakh Dec 19 '14 at 08:26
  • Great, I didn't even notice the thing about not having a^2 + c^2 = b^2. I put that in. I also changed the Math.pow. I still don't know what the problem is, though. I also don't really know what floating-point arithmetic is. – Frankmeister Dec 19 '14 at 10:53
  • 1
    The answer to this question gives a good link on floating-point arithmetic http://stackoverflow.com/questions/10334688/how-dangerous-is-it-to-compare-floating-point-values It's incredibly complicated but the basic thing to understand is that decimal types like `double` and `float` are extremely quick, but make tiny errors. Therefore if you compute a^2 + b^2 it may not come out the same as c^2 even if the triangle is right-angled. – Paul Boddington Dec 19 '14 at 11:01
  • 1
    @pbabcdefp Do not call `double` and `float` "decimal" types, because they are absolutely not. `decimal` (in C#) or `BigDecimal` (in Java) are decimal types. – C. K. Young Dec 19 '14 at 13:50
  • Fair point. I was using the word decimal when I meant non-integral. – Paul Boddington Dec 19 '14 at 13:51
2

Floating-point numbers are not exact, and comparisons using == will often fail. You should instead take the absolute difference between the two numbers and make sure it's very small:

private static boolean closeEnough(double a, double b) {
    return Math.abs(a - b) < 0x1p-32;
}

You can use a different threshold from 0x1p-32 if you want.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
1

If your method isRight() is supposed to to compute the answer from 3 floating point values, it will never work, because as others have pointed out you will get inaccuracies in your calculations. You may be happy to settle for a "close enough" approach like Chris Jester-Young's.

However, your triangles are specified using integer coordinates, so you don't need to use floating-point values. You can either do it using the squares of the three sides (as these will be integers) or you can do it by using gradients to see if any 2 sides are perpendicular. As this is a programming site rather than a maths site I won't give the details but it's possible to do it just using int addition, subtraction and multiplication, but, if you are smart, no division.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
  • I had a similar thought, but the question seems to be saying that the assignment came presupplied with code that computes `side1` and `side2` and `side3`, so presumably the intent was that the `isRight()` function make use of them? (But, +1 anyway. It's good advice in general.) – ruakh Dec 19 '14 at 08:30
  • Actually, side1 doesn't even need to exist. That would be a mistake on my part for that. I've just begun Java and I had no clue that the "close enough" thing was necessary for this type of work. Thanks for the help, I'll try to use that, too. – Frankmeister Dec 19 '14 at 10:57
  • It's not just java. You'd get the same issue in any other language. By the way, if all of your coordinates are integers, a^2 + b^2 and c^2 would both be integers. This means that if a^2 + b^2 and c^2 are not equal they would always differ by at least 1. This means that the threshold in the close enough thing doesn't need to be that small for it to work. I suspect Chris Jester-Young's approach will always give the correct answer for triangles with integer coordinates. – Paul Boddington Dec 19 '14 at 11:11
1

You didn't mentioned that how you are calculating Side1, Side2 and Side3 Assuming those are correct you second check in your function is same as first function there is no difference. So correct version would be

public boolean isRight() {

     return Math.pow(side1, 2) + Math.pow(side2, 2)) == Math.pow(side3, 2) ||
            Math.pow(side1, 2) + Math.pow(side3, 2)) == Math.pow(side2, 2) ||
            Math.pow(side3, 2) + Math.pow(side2, 2)) == Math.pow(side1, 2)

}
Mubashar
  • 12,300
  • 11
  • 66
  • 95
0

If your requirement is to check right angle based on 3 different set point entered, then you may refer to this below :)

Firstly a class for passing two points . (If you already have length of sides,then you may skip this)

public class Point {
private double x;
private double y;

public double getX() {
    return x;
}

public void setX(double x) {
    this.x = x;
}

public double getY() {
    return y;
}

public void setY(double y) {
    this.y = y;
}

public Point(double x, double y) {
    this.x=x;
    this.y=y;
}

}

Class for finding if entered values belong to right angled triangle

public class CheckRightAngledTriangle {

/**
 * Method to check if entered 3 sides belong to right angled triangle
 * 
 * @param a
 * @param b
 * @param c
 * @return
 */
boolean isRightAngledTriangle(Point a, Point b , Point c){
    Double lengthA = getLength(a,b);
    Double lengthB = getLength(b,c);
    Double lengthC = getLength(c,a);
    return  Math.pow(lengthA, 2) + Math.pow(lengthB, 2) == Math.pow(lengthC, 2) ||
            Math.pow(lengthA, 2) + Math.pow(lengthC, 2) == Math.pow(lengthB, 2) ||
            Math.pow(lengthC, 2) + Math.pow(lengthB, 2) == Math.pow(lengthA, 2);
}

/**
 * Method to get length between two points
 * 
 * @param point1
 * @param point2
 * @return
 */
public double getLength(Point point1 , Point point2){
    return Math.sqrt((point2.getX()-point1.getX())*(point2.getX()-point1.getX()) + (point2.getY()-point1.getY())*(point2.getY()-point1.getY()));

}

/**
 * Main method
 * 
 * @param args
 */
public static void main(String[] args) {
    Point pointA = new Point(5, 0);
    Point pointB = new Point(0, 0);
    Point pointC = new Point(1.8, 2.4);
    CheckRightAngledTriangle angledTriangle = new CheckRightAngledTriangle();
    System.out.println("Result is :"+angledTriangle.isRightAngledTriangle(pointA,pointB,pointC));

}