现欲构造一个三角形求周长和面积完整的解决方案,下面是代码,有5个构造方法:
1.正三角形,构造参数1个边长;
2.直角三角形,构造参数2个直角边;
3.已知三边的任意三角形,构造参数3个边;
4.已知两相连两边及其夹角,构造参数2个边和1个夹角;
5.已知两角及其夹边, 构造参数2个角和1个夹边;
问题是:
1.构造方法3,4,5的参数都为3个,我采用把角的参数为float, 不知有什么缺陷。
2.有没有其他构造方法没写?
3.如果要写set方法, 如 setSides, 那么其他变量,角度、周长、面积也会跟着变,那该怎么处理呢?
4.是不是我的这个类根本的思路就不对?
 /*
 * Triangle.java
 * @author Wenzee Yann, [email protected]
 * @version 0.1000
 * @since 2009.05.04
 */public class Triangle {
// 正三角形
public Triangle(double side) {
this.side1 = side;
this.side2 = side;
this.side3 = side;
this.angle1 = Math.PI / 3;
this.angle2 = Math.PI / 3;
this.angle3 = Math.PI / 3;
this.perimeter = 3 * side; // L = 3*a
this.area = Math.pow(side1, 2) * Math.sin(Math.PI / 3); //s = a*a*sin(π/3)
}
// 已知两直角边的直角三角形
public Triangle(double side1, double side2) {
this.side1 = side1;
this.side2 = side2;
this.side3 = Math.sqrt(side1 * side1 + side2 + side2);
this.angle1 = Math.atan(side1 / side2);
this.angle2 = Math.PI / 2 - this.angle1;
this.angle3 = Math.PI / 2;
this.perimeter = this.side1 + this.side2 + this.side3;
this.area = this.side1 * this.side2;
}
/* 已知三边的任意三角形
 * 余弦定理:a2=b2+c2-2bccosA, b2=a2+c2-2accosB, c2=a2+b2-2abcosC 
 * 三角形一边的平方等于另两边的平方和再减去这两边与夹角余弦的乘积的2倍 
 */
public Triangle(double side1, double side2, double side3) {
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
this.angle1 = Math.acos((this.side2 * this.side2
+ this.side3 + this.side3 - this.side1 * this.side1)
/ 2*  this.side2 * this.side3); //余弦定理
this.angle2 = Math.acos((this.side1 * this.side1
+ this.side3 + this.side3 - this.side2 * this.side1)
/ 2*  this.side1 * this.side3); //余弦定理
this.angle3 = Math.PI - this.side1 - this.side2;
this.perimeter = this.side1 + this.side2 + this.side3;
this.area = this.side1 * this.side2 * Math.cos(this.angle3);
}
/* 已知两相连两边及其夹角
 * 正弦定理: a/sinA=b/sinB=c/sinC=2R, 其中R是三角形外接圆半径。
 * 余弦定理:a2=b2+c2-2bccosA, b2=a2+c2-2accosB, c2=a2+b2-2abcosC 
 */
public Triangle(double side1, double side2, float angle3) {
this.side1 = side1;
this.side2 = side2;
this.side3 = Math.sqrt(this.side1 * this.side1 
+ this.side2 *  this.side2
- 2 * side1 * side2 *  Math.cos(angle3)); //余弦定理
this.angle3 = angle3;
this.angle1 = Math.asin(this.side1 * Math.sin(this.angle3)
/ this.side3); //正弦定理
this.angle2 = Math.PI /2 - this.angle1 - this.angle2;
this.perimeter = this.side1 +  this.side2 + this.side3;
this.area = this.side1 * this.side2 * Math.cos(this.angle3);
}
/* 已知两角及其夹边
 * 正弦定理: a/sinA=b/sinB=c/sinC=2R, 其中R是三角形外接圆半径。
 */
public Triangle(double side1, float angle2, float angle3) {
this.angle1 = Math.PI - angle2 -angle3;
this.angle2 = angle2;
this.angle3 = angle3;
this.side1 = side1;
this.side2 = this.side1 * Math.sin(this.angle2)
/ Math.sin(this.angle1); //正弦定理
this.side3 = this.side1 * Math.sin(this.angle3)
/ Math.sin(this.angle1); //正弦定理
this.perimeter = this.side1 +  this.side2 + this.side3;
this.area = this.side1 * this.side2 * Math.cos(this.angle3);
}
public double getSide1() {
return side1;
}
public double getSide2() {
return side2;
}
public double getSide3() {
return side3;
}
public double getAngle1() {
return angle1;
}
public double getAngle2() {
return angle2;
}
public double getAngle3() {
return angle3;
}
public double getPerimeter() {
return perimeter;
}
public double getArea() {
return area;
}
private double side1;
private double side2;
private double side3;
private double angle1; //side1对应角
private double angle2; //side2对应角
private double angle3; //side3对应角
private double perimeter; // 周长
private double area; // 面积
} // end class

解决方案 »

  1.   

    如果这个类是final的,我觉得整体思路上没什么问题.有几个细节再把握下
    1.将度数也设为double,设想你new时传递参数是写90度方便,还是写90f度方便.
    2.构造函数太独立了,各个构造函数没有联系性。比如说任意三边如果能判定是正三角就可以直接调用正三角的构造函数...
    3.感觉这个类如果写get方法还好,如果写set方法有点麻烦,传进参数时得重新判定此参数和其他两个参数构成三角形的条件能不能成立,建议单独写个异常类抛出异常
    4.这个类的重点主要是把握住传递进去的参数能不能构成三角形,还是建议单独写个判断是不是成立的异常类。
      

  2.   

    这是我以前做的求三角形的面积  Point类是一个点的坐标类 
    可以不用判断是什么三角形,直接求面积和周长package shape;public class Triangle {
    /**
     * point1,point2,point3为三角形的三点
     */
    private Point point1;
    private Point point2;
    private Point point3;

    public Triangle() {
    super();
    }
    /**
     * 构造方法 
     * @param point1 Point型
     * @param point2 Point型
     * @param point3 Point型
     */
    public Triangle(Point point1, Point point2, Point point3) {
    super();
    this.point1 = point1;
    this.point2 = point2;
    this.point3 = point3;
    }

    public Point getPoint1() {
    return point1;
    }
    public void setPoint1(Point point1) {
    this.point1 = point1;
    }
    public Point getPoint2() {
    return point2;
    }
    public void setPoint2(Point point2) {
    this.point2 = point2;
    }
    public Point getPoint3() {
    return point3;
    }
    public void setPoint3(Point point3) {
    this.point3 = point3;
    }
    /**
     * 求三角形一条边A
     * @return double型
     */
    private double triangleA(){
    return Math.hypot(point1.getCoordinate_x()-point2.getCoordinate_x(),point1.getCoordinate_y()-point2.getCoordinate_y());
    }
    /**
     * 求三角形一条边B
     * @return double型
     */
    private double triangleB(){
    return Math.hypot(point1.getCoordinate_x()-point3.getCoordinate_x(),point1.getCoordinate_y()-point3.getCoordinate_y());
    }
    /**
     * 求三角形一条边C
     * @return double型
     */
    private double triangleC(){
    return Math.hypot(point2.getCoordinate_x()-point3.getCoordinate_x(),point2.getCoordinate_y()-point3.getCoordinate_y());
    }
    /**
     * 判断这三点是否可以构成三角形
     * @return boolean型
     */
    private boolean isTriangle(){
    if(Math.abs(this.triangleA()+this.triangleB()) > this.triangleC() && Math.abs(this.triangleA()-this.triangleB()) < this.triangleC()){
    return true;
    }
    else{
    return false;
    }
    }

    /**
     * 如果可以构成三角形求三角形的面积
     * 不可以构成三角形return 0;
     * @return double型
     */
    public double countArea(){
    if(!this.isTriangle()){
    return 0;
    }
    else{
    double p = (this.triangleA() + this.triangleB() + this.triangleC())/2;
    return Math.sqrt(p * (p - this.triangleA()) * (p - this.triangleB()) * (p - this.triangleC()));
    }
    }

    public static void main(String[] args){
    /* Point point1 = new Point(1,2);
    Point point2 = new Point(1,3);
    Point point3 = new Point(4,3);
    Triangle triangle = new Triangle(point1,point2,point3);

    System.out.println(triangle.countArea());
    */ Point point1 = new Point(0,0);
    Point point2 = new Point(0,4);
    Point point3 = new Point(3,0);
    Triangle triangle = new Triangle(point1,point2,point3);

    System.out.println(triangle.countArea());
    }
    }
      

  3.   

    求面积用海轮公式:
    已知三角形三边长为a,b,c.
    周长的一半p = (a+b+c)/2
    三角形面积=sqrt(p*(p-a)*(p-b)*(p-c))
      

  4.   

    4.是不是我的这个类根本的思路就不对?不能说不对,不过这个类看上去的确很“死板”。
    风格属于典型的结构化编程产物。
    功能不够灵活。你可以想象你的桌面上现在有一个“智能”的三角形“对象”的“实例”。
    你可以改变它的某些属性,包括但不限于三条边的长度,三个角的角度,周长属性,面积属性。
    每当你改变其中的某个属性,桌面上的三角形就会自动调整。海伦公式也好,正余弦定理也罢,编写一个auto_update过程,再只要GET/SET上述属性调用即可。
      

  5.   

    float没有问题,边和角都是实数集合。
    你的计算处理都在构造函数里完成了,还设置set方法有什么用?
    我觉得楼主可以对整体设计改一下,用一个abstract类做父类,其余的五个做子类继承。还有最好把计算处理的代码从构造函数里分离出来另做一个函数。
      

  6.   

    我觉得,如果你这个三角形是经常变的话,那么它的成员不需要那么多;
    正如你写的构造函数一样,可以只要三边,或者两边及夹角就好了(有了些条件,三角形就唯一确定了)。
    这样的话,需要做的就是(以三边为例):
    1. 写构造的时候要把不是以三边为参数的构造函数把三边计算出来
    2. 写出getter时,不是取三边的话,都要用运算,如取周长就返回a+b+c
    3. 写setter的时候,如是允许set角度,也是要把变化的边计算出来设回去...
      

  7.   

    1、构造函数应该要能够检查不可能的条件,并抛出异常。这个前面已经有人说了
    2、成员的数量,一般只要保存3条边的长度就可以确定三角形的属性了,不需要保存角度信息。在数据量的应用中,可以用时间来换取空间。lz可以权衡取舍
    3、如果是我来做这个class,我会做成只有getter,没有setter,三角形的属性,只能读,不能改,这样可以简化类的定义。可以参考字符串类的做法来实现属性的变化:obj=obj.modify(),函数复杂根据变化的内容,重新构造一个对象并返回,而不是直接在原对象上修改
      

  8.   

    <html>
    <body><div>
    asdfasf
    </div>
    </body>
    </html>
      

  9.   

    求面积用海轮公式: 
    已知三角形三边长为a,b,c. 
    周长的一半p = (a+b+c)/2 
    三角形面积=sqrt(p*(p-a)*(p-b)*(p-c)) 
     这个方法更实用一点,当然前提是这个是三角形,要是连三角形都不是那么(a+b>=c||a-b<=c)
      

  10.   

    已经是一个三角形了,怎么能 set 其中的一个参数呢?不管把三边中的一边,还是三角中的一角设成其他的值,都无法再构成三角形了!
      

  11.   

    边和角在数学意义上来说是不同的类型,而你只是仅仅采用 double 和 float 来分开说明,
    我认为在面向对象的意义上来说是说不过去的。可以定义一个 Line 类和 Angle 类分别表示边和角。
      

  12.   

    构造方法3,4,5的参数都为3个,我采用把角的参数为float, 不知有什么缺陷。 
    这个肯定有问题啊,方法重载需要有不同的参数
      

  13.   

    1.构造方法3,4,5的参数都为3个,我采用把角的参数为float, 不知有什么缺陷。缺陷大大的。建议用静态方法取代构造函数,参见《effective java》第一条。比如,可以这样写:class Triangle {
       public static Triangle sideSideSide(double s, double s, double s) {..}
       public static Triangle sideAngleSide(double s, double a, double s) {...}
       public static Triangle angleSideAngle(double a, double s, double a) {...}
    }//example
    Triangle one = Triangle.sideSideSide(3,4,5);
      

  14.   

    不好意思,参数有重名的。
    改成
    sideSideSide(double s1, double s2, double s3)
    ...
      

  15.   

    */public class Triangle {
        // 正三角形
        public Triangle(double side) {
            this.side1 = side;
            this.side2 = side;
            this.side3 = side;
            this.angle1 = Math.PI / 3;
            this.angle2 = Math.PI / 3;
            this.angle3 = Math.PI / 3;
            this.perimeter = 3 * side;    // L = 3*a
            this.area = Math.pow(side1, 2) * Math.sin(Math.PI / 3);    //s = a*a*sin(π/3)
        }
        // 已知两直角边的直角三角形
        public Triangle(double side1, double side2) {
            this.side1 = side1;
            this.side2 = side2;
            this.side3 = Math.sqrt(side1 * side1 + side2 + side2);
            this.angle1 = Math.atan(side1 / side2);
            this.angle2 = Math.PI / 2 - this.angle1;
            this.angle3 = Math.PI / 2;
            this.perimeter = this.side1 + this.side2 + this.side3;
            this.area = this.side1 * this.side2;
        }    public Triangle(double side1, double side2, double side3) {
            this.side1 = side1;
            this.side2 = side2;
            this.side3 = side3;
            this.angle1 = Math.acos((this.side2 * this.side2
                    + this.side3 + this.side3 - this.side1 * this.side1)
                    / 2*  this.side2 * this.side3);    //余弦定理
            this.angle2 = Math.acos((this.side1 * this.side1
                    + this.side3 + this.side3 - this.side2 * this.side1)
                    / 2*  this.side1 * this.side3);    //余弦定理
            this.angle3 = Math.PI - this.side1 - this.side2;
            this.perimeter = this.side1 + this.side2 + this.side3;
            this.area = this.side1 * this.side2 * Math.cos(this.angle3);
        }
     
        public Triangle(double side1, double side2, float angle3) {
            this.side1 = side1;
            this.side2 = side2;
            this.side3 = Math.sqrt(this.side1 * this.side1 
                    + this.side2 *  this.side2
                    - 2 * side1 * side2 *  Math.cos(angle3));    //余弦定理
            this.angle3 = angle3;
            this.angle1 = Math.asin(this.side1 * Math.sin(this.angle3)
                    / this.side3);    //正弦定理
            this.angle2 = Math.PI /2 - this.angle1 - this.angle2;    
            this.perimeter = this.side1 +  this.side2 + this.side3;
            this.area = this.side1 * this.side2 * Math.cos(this.angle3);
        }
        /* 已知两角及其夹边
         * 正弦定理: a/sinA=b/sinB=c/sinC=2R, 其中R是三角形外接圆半径。
         */
        public Triangle(double side1, float angle2, float angle3) {
            this.angle1 = Math.PI - angle2 -angle3;
            this.angle2 = angle2;
            this.angle3 = angle3;
            this.side1 = side1;
            this.side2 = this.side1 * Math.sin(this.angle2)
                / Math.sin(this.angle1); //正弦定理
            this.side3 = this.side1 * Math.sin(this.angle3)
            / Math.sin(this.angle1); //正弦定理
            this.perimeter = this.side1 +  this.side2 + this.side3;
            this.area = this.side1 * this.side2 * Math.cos(this.angle3);
        }
        public double getSide1() {
            return side1;
        }
        public double getSide2() {
            return side2;
        }
        public double getSide3() {
            return side3;
        }
        public double getAngle1() {
            return angle1;
        }
        public double getAngle2() {
            return angle2;
        }
        public double getAngle3() {
            return angle3;
        }
        public double getPerimeter() {
            return perimeter;
        }
        public double getArea() {
            return area;
        }
    }
    }
      

  16.   

    Sharpen your code-java高级群:78455879欢迎您的加入...
      

  17.   

    也可以用S⊿= 1/2a*h = 1/2absinc= 1/2bcsina = 1/2acsinb等的解法。
      

  18.   

    //已知三条边和外接圆半径,公式为s = a*b*c/(4*R)
    double GetArea(double a, double b, double c, double R)
    {
    return a*b*c/4/R;
    }
    //已知三条边和内接圆半径,公式为s = pr
    double GetArea(double a, double b, double c, double r)
    {
    return r*(a+b+c)/2;

    //已知三角形三条边,求面积
    double GetArea(doule a, double b, double c)
    {
    double p = (a+b+c)/2;
    return sqrt(p*(p-a)*(p-b)*(p-c));
    }//已知道三角形三个顶点的坐标struct Point
    {
    double x, y;
    Point(double a = 0, double b = 0)
    {
       x = a; y = b;
    }
    };
    double GetArea(Point p1, Point p2, Point p3)
    {
    double t = -p2.x*p1.y+p3.x*p1.y+p1.x*p2.y-p3.x*p2.y-p1.x*p3.y+p2.x*p3.y;
    if(t < 0) t = -t;
    return t/2;
    }
      

  19.   

    海伦公式 就可以解决了
    WWW.BAIDU.COM
      

  20.   

    可以定义一个 Line 类和 Angle 类分别表示边和角。这个想法好,可以考虑一下,也有很大的发展空间……
    学习了!!!!!!
      

  21.   

    经过对各位出自人道主义的帮助和讲解,我回家仔细分析后认为:
    应该对我的Triangle类做以下处理:
    1.首先应该搞清楚的是要写几个类,我的理解是这样的:
       如果只是通过边长来改变Triangle,那么直需要写一个类;
       如果有时候需要通过边长,有时候通过角度来改变Triangle,那么需要写几个类,
       他们继承 abstract Triangle类。
       5楼kkiieerr007观点。
    2.所有不能写setter的实例域,及所有的计算变量都要去掉,而且不在constructor中求得,
      通过setter获取器值。
      21楼malligator的观点, 以及22楼rightyeah , 9楼xdop
    3.3楼wanghailong0115的类是用来画图的,我现在还没到这一步,以后需要画图时,再来借用。
    4.4楼sagegz说的海伦公式,我用上了,好用。
    5.61楼的groovy2007的<<effective java>>显然对我这个业余的初学者来说,还要等待一段时间。
    6.下面是我写的通过边长来改变Triangle,就写了一个类:/*
     * Triangle.java
     * @author [email protected], Wenzee Yann
     * @version 0.100, @since 2009.05.04
     */
    public class Triangle {
    //等边三角形
    public Triangle(double side) {
    this.sideA = this.sideB = this.sideC = side;
    }
    //等腰三角形
    public Triangle(double sideAB, double sideC) {
    this.sideA = this.sideB = sideAB;
    this.sideC = sideC;
    }
    //任意三边三角形
    public Triangle(double sideA, double sideB, double sideC) {
    this.sideA = sideA;
    this.sideB = sideB;
    this.sideC = sideC;
    }
    //两边及夹角
    public Triangle(double sideA, double sideB, float angleC) {
    this.sideA = sideA;
    this.sideB = sideB;
    // 余弦定理:a2=b2+c2-2bccosA, b2=a2+c2-2accosB, c2=a2+b2-2abcosC 
    this.sideC = Math.sqrt(sideA * sideA + sideB *  sideB
    - 2 * sideA * sideB *  Math.cos(Math.toRadians(angleC)));
    }
    //两角及夹边
    public Triangle(double sideA, float angleB, float angleC) {
    this.sideA = sideA;
    double angleA = 180 - angleB - angleC;
    // 正弦定理:a/singA = b/sinB = c/sinC = 2R
    this.sideB = (sideA / Math.sin(Math.toRadians(angleA)))
    * Math.sin(Math.toRadians(angleB));
    this.sideC = (sideA / Math.sin(Math.toRadians(angleA)))
    * Math.sin(Math.toRadians(angleC));
    }
    public double getSideA(){
     return sideA;
    }
    public double getSideB(){
    return sideB;
    }
    public double getSideC(){
    return sideC;
    }
    public double getAngleA() {
    return Math.toDegrees(Math.acos((sideB * sideB + sideC * sideC - sideA * sideA )
    / (2 * sideB * sideC))); // 余弦定理
    }
    public double getAngleB() {
    return Math.toDegrees(Math.acos((sideA * sideA + sideC * sideC - sideB * sideB)
    / (2 * sideA * sideC))); // 余弦定理
    }
    public double getAngleC() {
    return Math.toDegrees(Math.acos((sideA * sideA + sideB * sideB - sideC * sideC)
    / (2 * sideA * sideB))); // 余弦定理
    }
    public double getPerimeter() {
    return sideA +sideB + sideC;
    }
    public double getArea() {
    double p = (sideA + sideB + sideC) / 2;
    if ((sideA + sideB < sideC) 
    || Math.abs((sideA - sideB)) > sideC)
    return -1;
    else
    // 海伦公式 S =sqrt(P*(p-a)*(p-b)*(p-c)), p=(a+b+c)/2
    return  Math.sqrt(p * (p - sideA) 
    * (p - sideB) * (p - sideC));
    }
    public void setSideA(double sideA) {
    this.sideA = sideA;
    }
    public void setSideB(double sideB) {
    this.sideB = sideB;
    }
    public void setSideC(double sideC) {
    this.sideC = sideC;
    }
    private double sideA;
    private double sideB;
    private double sideC;
    }