"Domain error" 从 sqrt() 绘制椭圆时?
"Domain error" from sqrt() when drawing an ellipse?
使用多项式算法绘制椭圆的程序。
#include< graphics.h>
#include< stdio.h>
#include< math.h>
#include< conio.h>
void main() {
int gd=DETECT,gm;
float a,b,h,k;
float x,xend,y;
clrscr();
initgraph(&gd,&gm,"C:\TC\BGI");
printf("Enter the semi major axis and semi minor axis:\n");
scanf("%f%f",&a,&b);
printf("\nEnter the center coordinates, (h,k):");
scanf("%f%f",&h,&k);
xend=a;
for(x=0;x<=xend;x = x+0.1){
y=b*sqrt(1-(x*x)/(a));
putpixel(x+h,y+k,RED);
putpixel(-x+h,y+k,RED);
putpixel(-x+h,-y+k,RED);
putpixel(x+h,-y+k,RED);
}
getch();
//closegraph();
}
/*
输出
输入半长轴和半短轴:
200 130
输入中心坐标,(h,k):
200 230
*/
程序的输出显示
sqrt: 域错误
如何解决这个错误。
您的问题在这里:
for(x=0;x<=xend;x = x+0.1){
y=b*sqrt(1-(x*x)/(a));
X
一开始是 0,如果除法结果小于 1,1 - (x * x) / (a)
可以是负数。1 - (0 * 0) / (a) 将是 1大多数情况(a == 0 是一个特例)。因此,您将负值传递给 sqrt
,它需要正值。实际上,如果结果的域是复数集,也可以计算负数的平方根,但不幸的是 sqrt
不适用于该目的。
这里有几个问题:
域错误是由于将非法参数传递给 sqrt
而导致的。 sqrt
函数采用非负参数和 returns 非负平方根。在调用 sqrt
之前检查平方根(判别式)的参数是个好主意,除非您可以绝对确定该参数有效。
在你的循环中,你累积了浮点数。这样的加法是不准确的,尤其是当你做了很多累加时。最好用整数来控制你的循环,然后从这些整数中计算出一个浮点数。
您的公式不正确。省略号描述为
(x/a)² + (y/b)² = 1
您在此处的分母中遗漏了一个 a
。 (使用归一化的 rnning 变量可能会更好。)
将所有这些放在一起:
#include <stdio.h>
#include <math.h>
int main()
{
float a = 200.0f;
float b = 130.0f;
int i;
int n = 50;
for (i = 0; i <= n; i++) {
float c = 1.0f * i / n; // normalised x
float x = a * c; // actual x
float discr = 1.0f - c*c; // calc. discriminat separately ...
float y = (discr <= 0) ? 0 // ... so we can check it
: b * sqrtf(discr);
printf("%20.12f%20.12f\n", x, y);
}
return 0;
}
(当然,第三点是最重要的。当你处理离散像素时,将你的 运行 变量递增 1.0 也可能是有问题的。)
使用多项式算法绘制椭圆的程序。
#include< graphics.h>
#include< stdio.h>
#include< math.h>
#include< conio.h>
void main() {
int gd=DETECT,gm;
float a,b,h,k;
float x,xend,y;
clrscr();
initgraph(&gd,&gm,"C:\TC\BGI");
printf("Enter the semi major axis and semi minor axis:\n");
scanf("%f%f",&a,&b);
printf("\nEnter the center coordinates, (h,k):");
scanf("%f%f",&h,&k);
xend=a;
for(x=0;x<=xend;x = x+0.1){
y=b*sqrt(1-(x*x)/(a));
putpixel(x+h,y+k,RED);
putpixel(-x+h,y+k,RED);
putpixel(-x+h,-y+k,RED);
putpixel(x+h,-y+k,RED);
}
getch();
//closegraph();
}
/*
输出
输入半长轴和半短轴:
200 130
输入中心坐标,(h,k):
200 230
*/
程序的输出显示
sqrt: 域错误
如何解决这个错误。
您的问题在这里:
for(x=0;x<=xend;x = x+0.1){
y=b*sqrt(1-(x*x)/(a));
X
一开始是 0,如果除法结果小于 1,1 - (x * x) / (a)
可以是负数。1 - (0 * 0) / (a) 将是 1大多数情况(a == 0 是一个特例)。因此,您将负值传递给 sqrt
,它需要正值。实际上,如果结果的域是复数集,也可以计算负数的平方根,但不幸的是 sqrt
不适用于该目的。
这里有几个问题:
域错误是由于将非法参数传递给
sqrt
而导致的。sqrt
函数采用非负参数和 returns 非负平方根。在调用sqrt
之前检查平方根(判别式)的参数是个好主意,除非您可以绝对确定该参数有效。在你的循环中,你累积了浮点数。这样的加法是不准确的,尤其是当你做了很多累加时。最好用整数来控制你的循环,然后从这些整数中计算出一个浮点数。
您的公式不正确。省略号描述为
(x/a)² + (y/b)² = 1
您在此处的分母中遗漏了一个
a
。 (使用归一化的 rnning 变量可能会更好。)
将所有这些放在一起:
#include <stdio.h>
#include <math.h>
int main()
{
float a = 200.0f;
float b = 130.0f;
int i;
int n = 50;
for (i = 0; i <= n; i++) {
float c = 1.0f * i / n; // normalised x
float x = a * c; // actual x
float discr = 1.0f - c*c; // calc. discriminat separately ...
float y = (discr <= 0) ? 0 // ... so we can check it
: b * sqrtf(discr);
printf("%20.12f%20.12f\n", x, y);
}
return 0;
}
(当然,第三点是最重要的。当你处理离散像素时,将你的 运行 变量递增 1.0 也可能是有问题的。)