特定的直角三角形在 Cpp 中未被识别为直角
Specific right-angled Triangles are not being recognized as right-angled in Cpp
我们的 OOP 老师给我布置了一个作业。尽管我的代码看起来不错,但我遇到了这个问题。
我必须从用户那里获取三角形顶点的坐标,并且必须判断它是否是 r 直角三角形。所以我干脆用毕达哥拉斯定理求出来了,大家都知道用条件:h * h = b * b + p * p
但令人惊讶的是,这 不适用于某些特定的直角三角形 。
这是一个这样的三角形:
顶点 A:(x, y) = (1, 3)
顶点 B:(x, y) = (1, 1)
顶点 C:(x, y) = (5, 1)
它计算完美,我通过打印计算得出了这一点,但仍然不起作用。
然后我尝试以这种方式使用 cmath
库中的 sqrt()
函数:
h = sqrt(b * b + p * p)
逻辑上是一样的,但它起作用了。
我想明白,为什么前面的方法不行?
这是我的代码的简化版本:
#include <iostream>
#include <cmath>
using namespace std;
class Vertex {
double x, y;
public:
void take_input(char obj) {
cout << endl << " Taking Coordinates of Vertex " << obj << ": " << endl;
cout << " Enter the x component: ";
cin >> x;
cout << " Enter the y component: ";
cin >> y;
}
double distance(Vertex p) {
double dist = sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
return dist;
}
};
class Triangle {
Vertex a, b, c;
public:
void take_inp(string obj) {
cout << endl << "Taking Vertices of the Triangle " << obj << ": " << endl;
cout << " Verteces should be in a counter clockwise order (as per convention)." << endl;
a.take_input('A');
b.take_input('B');
c.take_input('C');
}
void is_rt_ang() {
double h = a.distance(c)*a.distance(c);
double bp = a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c);
/*
// Strangely this attempt works which is logically the same:
double h = a.distance(c);
double bp = sqrt(a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c));
*/
if (h == bp) {
cout << "Angle is 90" << endl;
cout << h << " = " << bp << endl;
cout << "It is Right-Angled" << endl;
}
else {
cout << "Angle is not 90!" << endl;
cout << h << " != " << bp << endl;
cout << "It is Not a Right-Angled" << endl;
}
}
};
int main()
{
Triangle tri1, tri2;
tri1.take_inp("tri1");
tri1.is_rt_ang();
return 0;
}
在你的 is_rt_ang
函数中你假设你的斜边总是边 AC
,但你似乎没有做任何事情来验证这一点。
double h = a.distance(c)*a.distance(c);
double bp = a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c);
您可以尝试先计算所有距离的平方,(AC)^2
、(AB)^2
和 (BC)^2
,然后通过从三,然后做类似的事情:
bool isRightTriangle = max == (min1 + min2)
您也可能 运行 遇到某种浮点数舍入错误。比较浮点数时通常使用 epsilon
值,因为它们存在固有的舍入误差。如果您不需要浮点值,可以使用整数,或者如果您确实需要浮点值,请尝试在等式中使用 epsilon
值,例如:
abs(h - bp) <= epsilon
您应该能够在 Web 上找到有关浮点值、舍入误差和机器小数的更多信息。
这是 SO Q/A 的 link,其中讨论了浮点数学,可能对您来说是一个很好的资源:Is floating point math broken?
行
double dist = sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
在 Vertex::distance
方法中给出了平方根的近似值,它很少会与精确答案重合。这是因为大多数实数不能用浮点运算来表示。
但是在给定的代码示例中,您可以在没有 sqrt
的情况下进行。将 Vertex::distance
方法替换为方法
double distance_square(Vertex p) {
double dist_square = (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y);
return dist_square;
}
并在Triangle::is_rt_ang
中这样称呼它:
double h = a.distance_square(c);
double bp = a.distance_square(b) + b.distance_square(c);
这个解决方案仍然存在缺陷,因为浮点乘法也容易出现舍入误差。但是如果保证你将只使用整数坐标,你可以用整数替换代码中的所有双精度数,并且对于它们来说乘法没有问题(除了可能超出大数范围之外)。
编辑:还有关于打印的评论
It calculates perfectly, which I figured out by printing the
calculation, but still doesn't work.
打印双精度时,您需要手动设置精度以避免四舍五入。如果在你的代码中我替换了一行
cout << h << " != " << bp << endl;
与
cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed << h << " != " << bp << endl;
然后例如问题中的三角形我得到了输出
Angle is not 90!
20.000000000000004 != 20.000000000000000
It is Not a Right-Angled
要进行编译,您需要添加 #include <limits>
和 #include <iomanip>
。
我们的 OOP 老师给我布置了一个作业。尽管我的代码看起来不错,但我遇到了这个问题。
我必须从用户那里获取三角形顶点的坐标,并且必须判断它是否是 r 直角三角形。所以我干脆用毕达哥拉斯定理求出来了,大家都知道用条件:h * h = b * b + p * p
但令人惊讶的是,这 不适用于某些特定的直角三角形 。 这是一个这样的三角形:
顶点 A:(x, y) = (1, 3)
顶点 B:(x, y) = (1, 1)
顶点 C:(x, y) = (5, 1)
它计算完美,我通过打印计算得出了这一点,但仍然不起作用。
然后我尝试以这种方式使用 cmath
库中的 sqrt()
函数:
h = sqrt(b * b + p * p)
逻辑上是一样的,但它起作用了。
我想明白,为什么前面的方法不行?
这是我的代码的简化版本:
#include <iostream>
#include <cmath>
using namespace std;
class Vertex {
double x, y;
public:
void take_input(char obj) {
cout << endl << " Taking Coordinates of Vertex " << obj << ": " << endl;
cout << " Enter the x component: ";
cin >> x;
cout << " Enter the y component: ";
cin >> y;
}
double distance(Vertex p) {
double dist = sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
return dist;
}
};
class Triangle {
Vertex a, b, c;
public:
void take_inp(string obj) {
cout << endl << "Taking Vertices of the Triangle " << obj << ": " << endl;
cout << " Verteces should be in a counter clockwise order (as per convention)." << endl;
a.take_input('A');
b.take_input('B');
c.take_input('C');
}
void is_rt_ang() {
double h = a.distance(c)*a.distance(c);
double bp = a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c);
/*
// Strangely this attempt works which is logically the same:
double h = a.distance(c);
double bp = sqrt(a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c));
*/
if (h == bp) {
cout << "Angle is 90" << endl;
cout << h << " = " << bp << endl;
cout << "It is Right-Angled" << endl;
}
else {
cout << "Angle is not 90!" << endl;
cout << h << " != " << bp << endl;
cout << "It is Not a Right-Angled" << endl;
}
}
};
int main()
{
Triangle tri1, tri2;
tri1.take_inp("tri1");
tri1.is_rt_ang();
return 0;
}
在你的 is_rt_ang
函数中你假设你的斜边总是边 AC
,但你似乎没有做任何事情来验证这一点。
double h = a.distance(c)*a.distance(c);
double bp = a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c);
您可以尝试先计算所有距离的平方,(AC)^2
、(AB)^2
和 (BC)^2
,然后通过从三,然后做类似的事情:
bool isRightTriangle = max == (min1 + min2)
您也可能 运行 遇到某种浮点数舍入错误。比较浮点数时通常使用 epsilon
值,因为它们存在固有的舍入误差。如果您不需要浮点值,可以使用整数,或者如果您确实需要浮点值,请尝试在等式中使用 epsilon
值,例如:
abs(h - bp) <= epsilon
您应该能够在 Web 上找到有关浮点值、舍入误差和机器小数的更多信息。
这是 SO Q/A 的 link,其中讨论了浮点数学,可能对您来说是一个很好的资源:Is floating point math broken?
行
double dist = sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
在 Vertex::distance
方法中给出了平方根的近似值,它很少会与精确答案重合。这是因为大多数实数不能用浮点运算来表示。
但是在给定的代码示例中,您可以在没有 sqrt
的情况下进行。将 Vertex::distance
方法替换为方法
double distance_square(Vertex p) {
double dist_square = (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y);
return dist_square;
}
并在Triangle::is_rt_ang
中这样称呼它:
double h = a.distance_square(c);
double bp = a.distance_square(b) + b.distance_square(c);
这个解决方案仍然存在缺陷,因为浮点乘法也容易出现舍入误差。但是如果保证你将只使用整数坐标,你可以用整数替换代码中的所有双精度数,并且对于它们来说乘法没有问题(除了可能超出大数范围之外)。
编辑:还有关于打印的评论
It calculates perfectly, which I figured out by printing the calculation, but still doesn't work.
打印双精度时,您需要手动设置精度以避免四舍五入。如果在你的代码中我替换了一行
cout << h << " != " << bp << endl;
与
cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed << h << " != " << bp << endl;
然后例如问题中的三角形我得到了输出
Angle is not 90!
20.000000000000004 != 20.000000000000000
It is Not a Right-Angled
要进行编译,您需要添加 #include <limits>
和 #include <iomanip>
。