# Thread: my first program. works perfectly but i dont understand why. few newbie questions.

1. ## my first program. works perfectly but i dont understand why. few newbie questions.

hey there guys.

i wrote a program to calculate the roots of a cubic equation using Cardanos formula, it works great so far i posted a thread asking for help on using the pow() function and i was having trouble getting a function prototype to work, but that sorted out now, i think.

im really happy i got this working. im so pleased i did it myself!! i only needed a tiny bit of help and i figured the rest out now the issues im having.

questions:

1. is there a pi function in C or do i have to define PI like that each time?

2. i dont understand how my sign function works(i have no idea how i actually managed to write it with almost no problems)

this is what i understand of it

i declare at the beginning of my program

float sign(float S); /* sign function prototype */

this tells the compiler that i've declared a function to be used in the main(), so when it reaches this function it knows that it exists.

then at the end of my function i wrote the function itself as

Code:
```float sign(float S)
{
if (S > 0)
return 1;
else if (S < 0)
return -1;
else
return 0;
}```
okay what i understand of this is that the float sign(float S) means, sign(float S) is expecting to be a floating point result. im more of a mathematician so ill speak in terms more familiar to me.

sign(float S) means f(x) where the input x will be a decimal/floating point number, this is correct

the output of this function will always be 1, -1 or 0, so can i define this function as

int sign(float S)?

does this save space or make it "better" or something?

furthermore - is S a global variable as i have defined it outside my main body? this is to say that, could i write sign function as...

int sign(float n), then when i call the function, use it as sign(S) later in the main body?

3.

when i wrote this part of the code

Code:
```Q = (b*b - 3.*c)/(9.0);
S = (2.*b*b*b - 9.*b*c + 27.*d)/(54.0);```
my professor explained that the . after the numbers was important, i dont remember why.. infact i have no idea why. as practice in our lab class we wrote a quadratic program and the numbers used in calculating the discriminant were of the same for, eg: 2.*d*d/3.0

how come i need the .'s there?

4. is this program clean and easy to understand?

is my constant use of if statements poor programming form? is there anything i can clean up?

this is the code

Code:
```#include <stdio.h>
#include <math.h>
#define PI (3.141592653589793238462643)

float Q, S, a, b, c, d, A1, x1, x2, x3, theta;

float sign(float S); /* sign function prototype */

int main()
{

/* Get coefficients from user */

printf("Cubic coefficient a? ");
scanf("%f", &a);

printf("Cubic coefficient b? ");
scanf("%f", &b);

printf("Cubic coefficient c? ");
scanf("%f", &c);

printf("Cubic coefficient d? ");
scanf("%f", &d);

/* Make sure a = 1, if it doesn't, recalculate the rest of the coefficents */

if (a != 1)
{
b = b/a; /* values of b, c, d must be calculated before a is set to 1 */
c = c/a;
d = d/a;
a = 1;
}

/* Now to do some calculations to be used later in the program */

Q = (b*b - 3.*c)/(9.0);
S = (2.*b*b*b - 9.*b*c + 27.*d)/(54.0);

/* temporary printf function to make sure results are being calculated correctly */

printf("%f = Q, %f = S, %f = a, %f = b, %f = c %f = d\n", Q, S, a, b, c, d);
printf("%f = sign(S) %f = A1\n", sign(S), A1);
printf("%f = Q*Q*Q - S*S\n", Q*Q*Q - S*S);

if (Q*Q*Q - S*S > 0)
{
theta = acos(S/sqrt(Q*Q*Q));
x1 = -2*sqrt(Q)*cos(theta/3.) - b/3.;
x2 = -2*sqrt(Q)*cos((theta + 2*PI)/3.) - b/3.;
x3 = -2*sqrt(Q)*cos((theta + 4*PI)/3.) - b/3.;

printf("The cubic has three real roots, %f = x1, %f = x2, %f = x3\n", x1, x2, x3);
}

if (Q*Q*Q - S*S <= 0)
{
A1 = -sign(S)*pow((sqrt(S*S - Q*Q*Q) + fabs(S)),1/3.);

if (A1 = 0)
{
x1 = A1 - b/3.;
printf("The cubic has only one real root, %f = x1\n", x1);
}
else
{
x1 = A1 + Q/A1 - b/3.;
printf("The cubic has only one real root, %f = x1\n", x1);
}
}

return 0;

}

float sign(float S)
{
if (S > 0)
return 1;
else if (S < 0)
return -1;
else
return 0;
}``` 2. 1) You can use the constant M_PI (defined in math.h) or, if you like, calculated it "on the fly" as the result of 4.0 * atan(1.0).

2)
a) It really doesn't matter much. Either way works fine (though I've usually seen it as an int).
b) The name of a function parameter has no binding outside of the function. If you have a global variable by the same name it won't be visible within the scope of that function though, obviously.

3) The '.' simply tell the compiler that it's a floating-point constant (as opposed to an integer).

4) It looks fine, although you could probably optimize things a bit by not doing repetitious calculations (eg: Q*Q*Q is used in several parts of the program whereas it could be calculated just once), and personally I'd be sure to leave space between operators and operands (eg: Q * Q * Q). 3. 1. No, but just define a constant. You may find non-standard M_PI in math.h

2. I'd declare it as int sign(const float s), as it makes more sense. Since floating points are approximations, and why approximate on -1, 0 and 1? (Even though at least 0 can be exactly represented as a float)

3. They are, since it makes them double constants, without them they would be integer constants and the resulting arithmetic would be different. i.e. x = (5 / 2), x is 2 since it's integer division, but x = (5. / 2), results in 2.5 since it's "floating point division".

4. It's mostly fine, but:
• Use more comments
• Why calculate the same thing twice? i.e. Q*Q*Q*Q, why not store the result in say, q4? Since you use it more than once.
• The variable names are pretty poor and nondescript. 4. About the return type of sign()

Whether it should be int or float depends on how you use it.
Remember, that comparing floating point numbers (especially using ==) is tricky, since the decimal representation is not what is internally used by computer. Hence it may be that the value looking exact, is not exact in the computer's point of view.

On the other hand, if sign() returns an int, then be carefull when you use it in calculations. Mixing floats and integers may get your result floored to nearest integer. 5. Why return 0 if and only if 's' equals 0? Doesn't that obfuscate the concept of signs?

Code:
```int sign(const float s) {

if( s >= 0)
return 1; // s is not negative

// s must be negative
return -1;
}``` Popular pages Recent additions 