C语言课程设计错误修改求赐教

woshilzh0 2018-07-04 10:55:22

本人今年大二,C语言做课程设计就是证明这道题: 对于任意的四边形ABCD,其对角线AC与BD的中点分别是M,N,AB,CD的延长线交于R.验证三角形RMN的面积是四边形ABCD面积的四分之一。在做的过程中遇到几个不明白的问题希望高手能赐教。 课本用的谭浩强的C程序设计(第五版)课程课时少,指针都没学完,就先用前面的知识解决问题, 发现这样几个问题:

1.面积证明大部分时候出错,计算出来的面积只有整数,但我用的是double型的数据,老师说肯定是因为我把某个高精度数据赋值给了int型的数据,但我检查确实没有,也就是说等号左边都是高精度数据类型,实在不知道问题在哪(比如0 0 4 0 4 4 0 2这一组数据成功,0 0 4 0 4 4 1 3这组数据失败)

2.老师禁止使用goto语句,说用循环代替,该怎么改(这学期也开了单片机,明明感觉用goto非常舒服思路清楚,无非就是思路更贴近汇编语言一样)

#include <stdio.h>

#include<math.h>

#include<windows.h>
int main()
{

int x1,y1,x2,y2,x3,y3,x4,y4,A1,A2,B1,B2,C1,C2;//改成float会出现死循环

double lab,lbc,lcd,lda,lac,lbd, xm,ym,xn,yn,xr,yr, labd,lbcd,lmn,lmr,lnr,lmnr;
double SABCD,SMNR;
START:
printf("依次输入A,B,C,D四点的坐标A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4),\n") ; //坐标有小数会出问题
scanf("%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
printf("A,B,C,D四点的坐标为A(%d,%d),B(%d,%d),C(%d,%d),D(%d,%d)\n",x1,y1,x2,y2,x3,y3,x4,y4);
if //筛选当输入的点有坐标重合的情况
(
(x1==x2&&y1==y2)
||(x1==x3&&y1==y3)
||(x1==x4&&y1==y4)
||(x2==x3&&y2==y3)
||(x2==x4&&y2==y4)
||(x3==x4&&y3==y4)
)
{
printf("A,B,C,D中至少有两点坐标有重合,请重新输入\n\n");
goto START;
}
A1=y2-y1;//计算直线AB和CD一般式的系数,不能使两直线平行
B1=x1-x2;
C1=x2*y1-x1*y2 ;
A2=y3-y4;
B2=x4-x3;
C2=x3*y4-x4*y3 ;
xm=(x1+x3)/2;//计算m,n两点坐标
ym=(y1+y3)/2;
xn=(x2+x4)/2;
yn=(y2+y4)/2;
lab=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); //计算四边形各个边长
lbc=sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3));

lcd=sqrt((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4));

lda=sqrt((x4-x1)*(x4-x1)+(y4-y1)*(y4-y1));
lbd=sqrt((x2-x4)*(x2-x4)+(y2-y4)*(y2-y4));//计算对角线长度
lac=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));
if((y2-y1)*x3+(x1-x2)*y3+x2*y1-x1*y2==0)
{
printf("A,B,C三点共线,请重新输入坐标使得三点不共线\n\n");
Sleep(5000);
goto START;
}
else if((y2-y1)*x4+(x1-x2)*y4+x2*y1-x1*y2==0)
{
printf("A,B,D三点共线,请重新输入坐标使得三点不共线\n\n");
Sleep(5000);
goto START;
}
else if(A1*B2==A2*B1&&C1!=C2)
{
printf("直线AB与直线CD平行,请重新输入坐标\n\n") ;
Sleep(5000);//windows.h头文件下命令,“s”小写以秒为单位,"S"大写以微秒为单位
goto START;
}

else if
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)>0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)>0
)
{
printf("A,B,C,D四点依次连接得到的不是一般四边形,请重新输入坐标使得对角线AC,BD不在四边形ABDC中交叉\n\n");
Sleep(5000);
goto START;
}
else if
(
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)>0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)<0
)
||
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)<0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)>0
)
)
{ printf("A,B,C,D四点依次连接得到的是凹四边形,请重新输入坐标使得四边形为凸四边形\n\n");
Sleep(5000);
goto START;
}
else
printf("ABCD顺次连接为一般四边形\nlab=%-1.2f\nlbc=%-1.2f\nlcd=%-1.2f\nlda=%-1.2f\n\n",lab,lbc,lcd,lda);
labd=(lab+lbd+lda)/2;
lbcd=(lbc+lcd+lbd)/2;
SABCD=sqrt(labd*(labd-lab)*(labd-lbd)*(labd-lda))+sqrt(lbcd*(lbcd-lbc)*(lbcd-lcd)*(lbcd-lbd));//得到四边形ABCD的面积
xr=(C2*B1-C1*B2)/(A1*B2-A2*B1) ;//计算AB,CD延长线的交点
yr=(A2*C1-A1*C2)/(A2*B1-A1*B2);
lmn=sqrt((xm-xn)*(xm-xn)+(ym-yn)*(ym-yn));//计算mn长度
lmr=sqrt((xm-xr)*(xm-xr)+(ym-yr)*(ym-yr));//计算mr长度
lnr=sqrt((xr-xn)*(xr-xn)+(yr-yn)*(yr-yn));//计算nr长度
lmnr=(lmn+lmr+lnr)/2;
SMNR=sqrt(lmnr*(lmnr-lnr)*(lmnr-lmr)*(lmnr-lmn));
if(SABCD-4*SMNR<0.00001&&SABCD-4*SMNR>-0.00001) //10^-6次方就不行,出现证明失败,极限就是-5次方怎么提高精度
{
printf("lmn=%-10.2f\nlnr=%-10.2f\nlmr=%-10.2f\n\n",lmn,lnr,lmr);
printf("四边形的面积为%-10.4f\n三角形MNR面积为%-10.4f\n",SABCD,SMNR);
printf("证明成功\n");
}
else
{
printf("lmn=%-10.2f\nlnr=%-10.2f\nlmr=%-10.2f\n\n",lmn,lnr,lmr);
printf("四边形ABCD的面积为%-10.4f\n三角形MNR面积为%-10.4f\n",SABCD,SMNR);
printf("证明失败\n") ;
}
return 0;
}
...全文
238 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
woshilzh0 2018-07-05
  • 打赏
  • 举报
回复
用循环的结构去掉了goto
if(SABCD-4*SMNR<0.00001&&SABCD-4*SMNR>-0.00001) //10^-6次方就不行,出现证明失败,极限就是-5次方怎么提高精度这个好像还是没办法
你说的数据精度我又用printf试了几个,和课本情况不一样
我把改的程序和精度实验的程序都贴出来

问题点:
0.0 0.0 4.0 0.0 4.0 4.0 1.0 3.0//这组面积是整数,成功了,但是面积不应该是整数
0.0 0.0 4.0 0.0 0.0 4.0 3.0 1.0//这组按照算法应该是认为交叉的才对,但是程序认为是一般四边形
0.0 0.0 4.1 0.1 0.0 3.9 2.9 1.1//这组只是让上组的数据略微浮动一下,但程序认为是凹四边形
1.1 1.2 4.5 0.3 0.3 3.1 4.3 4.2//这次让数据浮动的略微大一点,判断依次连接会交叉,这次正确了
1.1 1.2 4.5 0.3 4.3 4.2 0.3 3.1//判断没错,但是面积证明失败
0.2 0.3 123.0 0.5 96.5 95.2 12.3 56.5//这次换数据略微大一点,证明失败了


#include <stdio.h>
int main()
{float a;
double b;
b=1000/3;
a=1000/3;
printf("%f\n\n",(0.0000001)/2);//这个和你举得float的例子一样

printf("%lf\n\n",(0.0000001)/2);//以double的格式%lf去输出,结果也是一样的

printf("%1.10f\n\n",(0.0000001)/2);//在%f前修饰符,就把结果精确了,并且没有出现垃圾数

printf("%f\n\n",(10000)/3);//这个输出情况就比较费解了

printf("%1.10f\n\n",(10000)/3);//再加上修饰符也是没用的,和上面一样,多几个没用的零

{printf("%f\n\n",a); //这个就相当费解了,第一条我是照抄谭浩强书上的例子,他这个例子的结果是3333.33252,我们老师说
printf("%1.10f\n\n",a); //252那个就是垃圾数,随机数,系统内原来的存储空间中的数据,但是调试的结果连小数部分都
printf("%5.10f\n\n",a);}; //没有,并且也没有出现随机数,后面那个填1.10修饰符输出%f我自己试的,也是没用的

{printf("%f\n\n",b); //把数据类型换成double也同样不对
printf("%1.10f\n\n",b); //不知道是不是和编译器有关系…桌面上的图标名字是Microsoft Visual C++6.0,新建工程后,标题栏名字是这样:我自己随便起的文件名-创天中文VC++
printf("%5.10f\n\n",b);};

return 0;
}




#include <stdio.h>

#include<math.h>

#include<windows.h>
int main()
{

double x1,y1,x2,y2,x3,y3,x4,y4,A1,A2,B1,B2,C1,C2;

double lab,lbc,lcd,lda,lac,lbd, xm,ym,xn,yn,xr,yr, labd,lbcd,lmn,lmr,lnr,lmnr;
double SABCD,SMNR;
while(1)
{
printf("依次输入A,B,C,D四点的坐标A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4),\n");
scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);
printf("A,B,C,D四点的坐标为A(%lf,%lf),B(%lf,%lf),C(%lf,%lf),D(%lf,%lf)\n", x1, y1, x2, y2, x3, y3, x4, y4);
if
(

(x1==x2&&y1==y2)
||(x1==x3&&y1==y3)
||(x1==x4&&y1==y4)
||(x2==x3&&y2==y3)
||(x2==x4&&y2==y4)
||(x3==x4&&y3==y4)
)
{ printf("A,B,C,D中至少有两点坐标有重合,请重新输入\n\n") ;
continue;
};
A1=y2-y1;//计算直线AB和CD一般式的系数,不能使两直线平行
B1=x1-x2;
C1=x2*y1-x1*y2;
A2=y3-y4;
B2=x4-x3;
C2=x3*y4-x4*y3;
xm=(x1+x3)/2;//计算m,n两点坐标
ym=(y1+y3)/2;
xn=(x2+x4)/2;
yn=(y2+y4)/2;
lab=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); //计算四边形各个边长
lbc=sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3));
lcd=sqrt((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4));
lda=sqrt((x4-x1)*(x4-x1)+(y4-y1)*(y4-y1));
lbd=sqrt((x2-x4)*(x2-x4)+(y2-y4)*(y2-y4));//计算对角线长度
lac=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));
if((y2-y1)*x3+(x1-x2)*y3+x2*y1-x1*y2==0)
{
printf("A,B,C三点共线,请重新输入坐标使得三点不共线\n\n");
Sleep(5000);
continue;};

if((y2-y1)*x4+(x1-x2)*y4+x2*y1-x1*y2==0)
{
printf("A,B,D三点共线,请重新输入坐标使得三点不共线\n\n");
Sleep(5000);
continue; };

if(A1*B2==A2*B1&&C1!=C2)
{
printf("直线AB与直线CD平行,请重新输入坐标\n\n") ;
Sleep(5000); //windows.h头文件下命令,“s”小写以秒为单位,"S"大写以微秒为单位
continue; };
if
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)>0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)>0
)
{
printf("A,B,C,D四点依次连接得到的不是一般四边形,请重新输入坐标使得对角线AC,BD不在四边形ABDC中交叉\n\n");
Sleep(5000);
continue;};

if
(
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)>0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)<0
)
||
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)<0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)>0
)
)
{ printf("A,B,C,D四点依次连接得到的是凹四边形,请重新输入坐标使得四边形为凸四边形\n\n");
Sleep(5000);
continue;};


printf("ABCD顺次连接为一般四边形\nlab=%-1.2f\nlbc=%-1.2f\nlcd=%-1.2f\nlda=%-1.2f\n\n",lab,lbc,lcd,lda);
break;
};

labd=(lab+lbd+lda)/2;

lbcd=(lbc+lcd+lbd)/2;
SABCD=sqrt(labd*(labd-lab)*(labd-lbd)*(labd-lda))+sqrt(lbcd*(lbcd-lbc)*(lbcd-lcd)*(lbcd-lbd));//得到四边形ABCD的面积
xr=(C2*B1-C1*B2)/(A1*B2-A2*B1) ;//计算AB,CD延长线的交点
yr=(A2*C1-A1*C2)/(A2*B1-A1*B2);
lmn=sqrt((xm-xn)*(xm-xn)+(ym-yn)*(ym-yn));//计算mn长度
lmr=sqrt((xm-xr)*(xm-xr)+(ym-yr)*(ym-yr));//计算mr长度
lnr=sqrt((xr-xn)*(xr-xn)+(yr-yn)*(yr-yn));//计算nr长度
lmnr=(lmn+lmr+lnr)/2;
SMNR=sqrt(lmnr*(lmnr-lnr)*(lmnr-lmr)*(lmnr-lmn));
if(SABCD-4*SMNR<0.00001&&SABCD-4*SMNR>-0.00001) //10^-6次方就不行,出现证明失败,极限就是-5次方怎么提高精度
{
printf("lmn=%-10.2f\nlnr=%-10.2f\nlmr=%-10.2f\n\n",lmn,lnr,lmr);
printf("四边形的面积为%-10.4f\n三角形MNR面积为%-10.4f\n",SABCD,SMNR);
printf("证明成功\n");
}
else
{
printf("lmn=%-10.2f\nlnr=%-10.2f\nlmr=%-10.2f\n\n",lmn,lnr,lmr);
printf("四边形ABCD的面积为%-10.4f\n三角形MNR面积为%-10.4f\n",SABCD,SMNR);
printf("证明失败\n") ;
};
return 0;
}

_肆 2018-07-05
  • 打赏
  • 举报
回复
建议你这个也改了
SABCD = sqrt((lab + lda + lbd)*(lab + lda - lbd)*(lab - lda + lbd)*(-lab + lda + lbd) / 16.0)
+ sqrt((lbc + lcd + lbd)*(lbc + lcd - lbd)*(lbc - lcd + lbd)*(-lbc + lcd + lbd) / 16.0);//得到四边形ABCD的面积

然后我手算了下,你的延长线交点应该是这样yr = (A2*C1 - A1*C2) / (A1*B2 - A2*B1);你正好写的它的负值,然后你再检查你的xr对着没,我没算
_肆 2018-07-05
  • 打赏
  • 举报
回复
1、我没太研究过面积计算公式,就直接百度的,他给了三种方法:
(p=(a+b+c)/2)
S=sqrt[p(p-a)(p-b)(p-c)]
=sqrt[(1/16)(a+b+c)(a+b-c)(a+c-b)(b+c-a)]
=1/4sqrt[(a+b+c)(a+b-c)(a+c-b)(b+c-a)]

你用的第一种,然后我选的2和3应该差不多,区别就在于你用p这个东西的时候就已经产生误差了,然后带入算s的时候又把这个误差乘了四次,算是扩大误差,算上sqrt一共5次误差;而我这个就算有误差,也仅出现在sqrt和1/16,只有两次。加减是没误差的,乘除会有,尤其以中间变量的影响大,关于误差为什么产生,我可以以float举个例子,比如a+b+c等于0.000001,除2后应该是0.0000005,但是受float的精度影响,p的值等于0也是可能的,但是在2和3里面,首先进行的是加减法,不存在这种误差,算是减小误差。

2、%lf的表示,char用%c,int用%d,float用%f,double也应该有自己的,那就是%lf,虽然你没看出来区别,这就好比你用int 0和float 0.0,这都表示0一样,个例是看不出什么的,具体的原理可能很少有人去研究,而是把它当成一种书写习惯防患于未然,同理的东西有float精度6位是怎么算的、double的精度15位怎么算的、float和double用十六进制数表示怎么计算、我感觉这些很基础的东西,现在好像都不教了

3、/2和/2.0也算是书写规范,我在工程中遇到过/2的时候把前面的东西自动强转为int算的

4、我也编程没两年,如何精进谈不上,但是我觉得工作后开始做项目才算是突飞猛进的时候,在学校就是随便写点算法培养兴趣,至于书,我算是不踏实的一种把,一本没看过,凡事靠百度,goto这种东西也从来没用过,直觉编程里越是方便的东西越危险

5、你可以把你试验不行的点给我,我追断点看看问题出在哪,我也是全用小数试的,感觉差不多了,我也很好奇,其实对自己来说这种探索的过程是对基础知识的重认识和新知识的学习
woshilzh0 2018-07-05
  • 打赏
  • 举报
回复
贴代码的时候没看到回复,不好意思。你说的地方我改了,的确,yr的坐标算错了,但是xr的坐标是正确的
四边形的面积公式改过来了,之前光改了三角形面积,改了重新贴一下。


#include <stdio.h>

#include<math.h>

#include<windows.h>
int main()
{

double x1,y1,x2,y2,x3,y3,x4,y4,A1,A2,B1,B2,C1,C2;

double lab,lbc,lcd,lda,lac,lbd, xm,ym,xn,yn,xr,yr, labd,lbcd,lmn,lmr,lnr,lmnr;
double SABCD,SMNR;
while(1)
{
printf("依次输入A,B,C,D四点的坐标A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4),\n");
scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);
printf("A,B,C,D四点的坐标为A(%lf,%lf),B(%lf,%lf),C(%lf,%lf),D(%lf,%lf)\n", x1, y1, x2, y2, x3, y3, x4, y4);
if
(

(x1==x2&&y1==y2)
||(x1==x3&&y1==y3)
||(x1==x4&&y1==y4)
||(x2==x3&&y2==y3)
||(x2==x4&&y2==y4)
||(x3==x4&&y3==y4)
)
{ printf("A,B,C,D中至少有两点坐标有重合,请重新输入\n\n") ;
continue;
};
A1=y1-y2;//计算直线AB和CD一般式的系数,不能使两直线平行
B1=x2-x1;
C1=x1*y2-x2*y1;
A2=y3-y4;
B2=x4-x3;
C2=x3*y4-x4*y3;
xm=(x1+x3)/2;//计算m,n两点坐标
ym=(y1+y3)/2;
xn=(x2+x4)/2;
yn=(y2+y4)/2;
lab=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); //计算四边形各个边长
lbc=sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3));
lcd=sqrt((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4));
lda=sqrt((x4-x1)*(x4-x1)+(y4-y1)*(y4-y1));
lbd=sqrt((x2-x4)*(x2-x4)+(y2-y4)*(y2-y4));//计算对角线长度
lac=sqrt((x1-x3)*(x1-x3)+(y1-y3)*(y1-y3));
if((y2-y1)*x3+(x1-x2)*y3+x2*y1-x1*y2==0)
{
printf("A,B,C三点共线,请重新输入坐标使得三点不共线\n\n");
Sleep(5000);
continue;};

if((y2-y1)*x4+(x1-x2)*y4+x2*y1-x1*y2==0)
{
printf("A,B,D三点共线,请重新输入坐标使得三点不共线\n\n");
Sleep(5000);
continue; };

if(A1*B2==A2*B1&&C1!=C2)
{
printf("直线AB与直线CD平行,请重新输入坐标\n\n") ;
Sleep(5000); //windows.h头文件下命令,“s”小写以秒为单位,"S"大写以微秒为单位
continue; };
if
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)>0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)>0
)
{
printf("A,B,C,D四点依次连接得到的不是一般四边形,请重新输入坐标使得对角线AC,BD不在四边形ABDC中交叉\n\n");
Sleep(5000);
continue;};

if
(
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)>0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)<0
)
||
(
((y3-y1)*x2+(x1-x3)*y2+x3*y1-x1*y3)* ((y3-y1)*x4+(x1-x3)*y4+x3*y1-x1*y3)<0
&&
((y4-y2)*x1+(x2-x4)*y1-x2*y4+x4*y2)* ((y4-y2)*x3+(x2-x4)*y3-x2*y4+x4*y2)>0
)
)
{ printf("A,B,C,D四点依次连接得到的是凹四边形,请重新输入坐标使得四边形为凸四边形\n\n");
Sleep(5000);
continue;};


printf("ABCD顺次连接为一般四边形\nlab=%-1.2f\nlbc=%-1.2f\nlcd=%-1.2f\nlda=%-1.2f\n\n",lab,lbc,lcd,lda);
break;
};

labd=(lab+lbd+lda)/2;

lbcd=(lbc+lcd+lbd)/2;
SABCD = sqrt((lab + lda + lbd)*(lab + lda - lbd)*(lab - lda + lbd)*(-lab + lda + lbd) / 16.0)
+ sqrt((lbc + lcd + lbd)*(lbc + lcd - lbd)*(lbc - lcd + lbd)*(-lbc + lcd + lbd) / 16.0);//得到四边形ABCD的面积
xr=(C2*B1-C1*B2)/(A1*B2-A2*B1) ;//计算AB,CD延长线的交点
yr=(A1*C2-A2*C1)/(A2*B1-A1*B2);
lmn=sqrt((xm-xn)*(xm-xn)+(ym-yn)*(ym-yn));//计算mn长度
lmr=sqrt((xm-xr)*(xm-xr)+(ym-yr)*(ym-yr));//计算mr长度
lnr=sqrt((xr-xn)*(xr-xn)+(yr-yn)*(yr-yn));//计算nr长度
lmnr=(lmn+lmr+lnr)/2;
SMNR=sqrt(lmnr*(lmnr-lnr)*(lmnr-lmr)*(lmnr-lmn));
if(SABCD-4*SMNR<0.00001&&SABCD-4*SMNR>-0.00001) //10^-6次方就不行,出现证明失败,极限就是-5次方怎么提高精度
{
printf("lmn=%-10.2f\nlnr=%-10.2f\nlmr=%-10.2f\n\n",lmn,lnr,lmr);
printf("四边形的面积为%-10.4f\n三角形MNR面积为%-10.4f\n",SABCD,SMNR);
printf("证明成功\n");
}
else
{
printf("lmn=%-10.2f\nlnr=%-10.2f\nlmr=%-10.2f\n\n",lmn,lnr,lmr);
printf("四边形ABCD的面积为%-10.4f\n三角形MNR面积为%-10.4f\n",SABCD,SMNR);
printf("证明失败\n") ;
};
return 0;
}
_肆 2018-07-04
  • 打赏
  • 举报
回复
我修改了两个地方:
1、
float x1, y1, x2, y2, x3, y3, x4, y4, A1, A2, B1, B2, C1, C2;//改成float会出现死循环
。。。
scanf("%f%f%f%f%f%f%f%f", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);
printf("A,B,C,D四点的坐标为A(%f,%f),B(%f,%f),C(%f,%f),D(%f,%f)\n", x1, y1, x2, y2, x3, y3, x4, y4);
2、计算三角形面积公式改为
SMNR = sqrt((lmn + lmr + lnr)*(lmn + lmr - lnr)*(lmn - lmr + lnr)*(-lmn+lmr+lnr)/16.0);//这个好像精度更好一点

你说的两个例子我证明成功的,不知道你死循环的打印是啥样的;

但是因为你这个程序涉及到的浮点运算步骤太多了,每多一步就多一次误差,所以我试了一个全小数的坐标关系,证明失败了,误差在小数点3位,我再用断点追一下你的数,看有没有办法修正精度问题
woshilzh0 2018-07-04
  • 打赏
  • 举报
回复
按照你的第二段回复改上,随便打了几个点还是有不行的……有点费解
woshilzh0 2018-07-04
  • 打赏
  • 举报
回复
int x1,y1,x2,y2,x3,y3,x4,y4,A1,A2,B1,B2,C1,C2;//改成float会出现死循环
float lab,lbc,lcd,lda,lac,lbd, xm,ym,xn,yn,xr,yr, labd,lbcd,lmn,lmr,lnr,lmnr;
double SABCD,SMNR;
我是在这种情况下输入小数才出现死循环的 。这个求助帖子已经把中间那行float改成double了,才没出现死循环。我忘记修改注释了,不好意思。


printf("依次输入A,B,C,D四点的坐标A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4),\n") ;
scanf("%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
printf("A,B,C,D四点的坐标为A(%d,%d),B(%d,%d),C(%d,%d),D(%d,%d)\n",x1,y1,x2,y2,x3,y3,x4,y4);
我的知识储备仅仅限于谭浩强的那本C程序设计(第五版)指针往后还不会,%d我理解错了,%d只能输出十进制整数,我记成了可以输出任何十进制的数和double型的数据

%f输出的数据如果是float型的,只能保证6位有效数字,如果是double型的数据,可以保证15位有效数字
这个是我通过比较你的答案,再回头看书看明白的,看的时候不太仔细,误以为%f输出都只能是保证6位

你这个三角形面积的计算公式是什么?我那个是谭浩强那个课本上的例题,我查了下那个公式叫海伦公式
用你的这个公式确实可以多做出不少别的点的数据,不过我感觉都是用到了除法和开根号已知都是3条边……为什么你说这个公式精度更高,求赐教?

你发的第二段我看到了printf中有%lf,自己试了下,输出没区别啊……谭浩强的书也没在printf中出现过%lf这样的。这先留一下,我看看别的答案考虑考虑,如果再不懂就来问你……

常量也会有影响吗?这个完全涉及知识盲区了,常量和精度有什么关系……


最后就是请问一下,我学习编程接下来该如何精进呢?去找RQNOJ刷题练C语言?还是再学c++或java语法?还是看看C Primer Plus之类的更好的书?你推荐怎样的学习路线呢,求赐教……

最后就是,我怎么把悬赏的50分给你啊,超级感谢你的!用循环结构去取代goto语句我再看看吧,身边好多同学编程都出现了goto语句,但不知道怎么修改,有需要再请教你吧。

再次,炒鸡感谢,(づ ̄3 ̄)づ╭❤~




_肆 2018-07-04
  • 打赏
  • 举报
回复
成了

修改代码
double x1, y1, x2, y2, x3, y3, x4, y4, A1, A2, B1, B2, C1, C2;//改成float会出现死循环

printf("依次输入A,B,C,D四点的坐标A(x1,y1),B(x2,y2),C(x3,y3),D(x4,y4),\n");//坐标有小数会出问题 
scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4);
printf("A,B,C,D四点的坐标为A(%lf,%lf),B(%lf,%lf),C(%lf,%lf),D(%lf,%lf)\n", x1, y1, x2, y2, x3, y3, x4, y4);

然后可能会产生影响的是所有的常量,比如/2的地方,最好用2.0这样的表示

打印的时候没必要%.2f了,double精度很高的

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧