"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 也可能是有问题的。)