'"Domain error" from sqrt() when drawing an ellipse?

The program to draw an ellipse using polynominal algoritm.

#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();    

}    

/*

output

Enter the semi major axis and semi minor axis:

200 130

Enter the center coordinates, (h,k):

200 230

*/

The output of the program shows

sqrt: Domain error

How to solve this error.



Solution 1:[1]

There are several issues here:

  • The domain error results from passing an illegal argument to sqrt. The sqrt function takes a non-negative argument and returns the non-negative square root. It is a good idea to check the argument of the square root, the discriminant, before calling sqrt unless you can be absolutely sure that the argument is valid.

  • In your loop, you accumulate floating-point numbers. Such additions are inaccurate, especially if you do many accumulations. It is better to control your loop with integers and then calculate a floating-point number from these integers.

  • Your formula isn't correct. An ellipsis is described by

    (x/a)² + (y/b)² = 1
    

    You are missing one a in the denominator here. (It may be better to use a normalised rnning variable.)

Putting all this together:

#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;
}

(The third point is the most important, of course. When you deal with discrete pixels, it might also be questionable to increment your running variable by fractions of 1.0.)

Solution 2:[2]

Your problem is here:

for(x=0;x<=xend;x = x+0.1){    

    y=b*sqrt(1-(x*x)/(a));

X is 0 at the start and 1 - (x * x) / (a) can be negative if the division results in a value less than 1. 1 - (0 * 0) / (a) will be 1 in most cases (a == 0 is a special case). So, you pass a negative value to sqrt, which expects positive values. In reality one can calculate the square root of a negative number as well if the domain of the result is the set of Complex numbers, but, unfortunately sqrt is not applicable for that purpose.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Lajos Arpad