6
\$\begingroup\$

I have written a program in C that calculates local g, by using height from the sea level and latitude.

NOTE: I have to add an image of the equation because that website is no longer active.

Here's my code:

#include <stdio.h>
#include <math.h>

double local_g(double latitide, double height_sea_lvl);
double local_g(double latitide, double height_sea_lvl)
{
    const double A = 0.0053024;
    const double B = 0.0000058;

    double H2 = (0.000003 * height_sea_lvl);
    double s1 = (A * sin(latitide));

    double s2 = (B * sin(2 * latitide));
    return (double)(9.780327 * (1 + s1 - s2) - H2);
}

int main(void)
{
    printf("Enter latitude:\t");
    double latitude = 0, height = 0;
    if (scanf("%lf", &latitude) != 1)
    {
        fprintf(stderr, "bad input\n");
        return 1;
    }
    printf("Enter height above sea level (in metres):\t");
    if (scanf("%lf", &height) != 1)
    {
        fprintf(stderr, "bad input\n");
        return 1;
    }

    printf("Your local g (accleration due to gravity): %0.10f\n", local_g(latitude, height));
    return 0;
}

I compiled the above program using GCC v11.2.0 on Arch Linux

gcc -O3 -Ofast -Og -Os -s local_g.c -lm -o local_g

Can anyone suggests any sort of improvement for the above code, as I have followed most of the good C practices mentioned in many answer (highly up-voted one) on https://stackoverflow.com.

\$\endgroup\$
0

2 Answers 2

7
\$\begingroup\$

There's no need for the forward declaration of local_g() (especially as it's immediately followed by the definition). But it should be declared with static linkage.

Typo in the argument: should be latitude. Although this sounds trivial, consistently correct spelling can make large programs easier to search.

We specify the units when prompting for altitude, but not for latitude. The use directly in sin() suggests we need input in radians, which is certainly not what most users would expect. I'd suggest that input in degrees would be friendlier.

Top marks for actually testing whether the scanf() conversions were successful. Consider using the EXIT_FAILURE value as return value rather than bare 1 (it's defined in <stdlib.h>).

I've no idea whether the formula is correct (and it's obviously a simplification - real geodesy uses a parametric model that accounts for the non-uniform density of the Earth's crust). It doesn't match the formula in the image (which has A·sin²L and B·sin²2L rather than A·sin L and B·sin 2L), so I'm surprised this passes even the basic testing. Also, the height constant seems to have been mistranscribed - should be 3.086e-6 rather than 3e-6.

It seems that the constants A and B are directly taken from the formula, so those names are probably okay if there's no more descriptive word that fits. The other variables could be a bit more descriptive, I think.

The cast of the computation result (a double) to the same type is unnecessary clutter and should be omitted.

Printing to ten decimal places is probably too much given the claimed precision of the formula (±0.005%, i.e. 0.0005 m/s²). We should include units in the output (use of values with mis-assumed units is a known cause of engineering problems, especially if you have to work with US teams at any point).

There are no significant performance concerns in this function. Some platforms may have faster float computation than double (though that's not generally the case, and float can be slower) - that's something we can't determine for you, so you need to profile (and decide whether the loss of precision is worth any speed gain). You might consider -ffastmath compilation option, which will sacrifice correctness with strange values (subnormals, NaNs etc) for speed.

Your compiler flags don't include any warning options. I recommend at least -Wall -Wextra, and normally use quite a few more. When I compiled with my usual set of warnings, the code passed cleanly, but it's worth getting early notice of problems you introduce.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks, I really didn't noticed that I missed the sin^2 term. By the way equation is legit \$\endgroup\$ Mar 3 at 17:26
  • \$\begingroup\$ When I test my code I usually use -g -W -Wall -Wextra -Wuninitialized -Wstrict-aliasing -ggdb3 -std=c17 -Wextra -pedantic -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition, but if I remove that forward declaration I got prototype error \$\endgroup\$ Mar 3 at 17:48
  • 1
    \$\begingroup\$ I don't normally use -Wmissing-prototypes but it would make sense that it wants a header prototype for an external function. Something I missed from my review is that it should be declared with static linkage since it's local to the translation unit. Fixing that will appease the warning. \$\endgroup\$ Mar 3 at 22:11
2
\$\begingroup\$

Based on the accepted answer I have made some changes:

  • made local_g() function static
  • fixed the typo latitide --> latitude
  • removed unnecessary type-casting while returning the value of local_g() function
  • removed bare 1 and 0 now I'm using EXIT_FAILURE and EXIT_SUCCESS respectively
  • added unit and uncertainty to my final printf() statement
  • added unit when asking for latitude from the user
  • now only printing the first 4 decimal places instead of 10 decimal places
  • major bug: now calculating A·sin²L and B·sin²2L instead of A·sin L and B·sin 2L
  • using 3.086e-6 rather than 0.000003.
  • using quick_exit() function, because after printing "bad input\n", it prints "Enter height above sea level (in metres):\t"

Final Code: TRY IT CALIFORNIA

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

static double local_g(double latitude, double height_sea_lvl)
{
    const double A = 0.0053024;
    const double B = 0.0000058;

    double H2 = (3.086e-6 * height_sea_lvl);

    double s1 = (A * pow(sin(latitude), 2));
    double s2 = (B * pow(sin(2 * latitude), 2));

    return 9.780327 * (1 + s1 - s2) - H2;
}

int main(void)
{
    printf("Enter latitude (in radians):\t");
    double latitude = 0, height = 0;
    if (scanf("%lf", &latitude) != 1)
    {
        fprintf(stderr, "bad input\n");
        quick_exit(EXIT_FAILURE);
    }
    printf("Enter height above sea level (in metres):\t");
    if (scanf("%lf", &height) != 1)
    {
        fprintf(stderr, "bad input\n");
        quick_exit(EXIT_FAILURE);
    }
    printf("Your local g (accleration due to gravity): %0.4f ± 0.0005 m/s²\n", local_g(latitude, height));
    return EXIT_SUCCESS;
}
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.