'"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. Thesqrtfunction 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 callingsqrtunless 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)² = 1You are missing one
ain 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 |
