Home > Mobile >  How to calculate to the power of n in c without using pow or anything from the math.h library
How to calculate to the power of n in c without using pow or anything from the math.h library

Time:03-19

The task goes like this:

Write a program that calculates the power of a number (as a pow function from the "math.h" library), except the limitation here is that the exponent can only be an integer. The base and exponent are entered from the keyboard, where the base can be of the real type, while the exponent is a positive or negative integer. Attention should be paid to checking data entry; special treatment should be given to cases where the number is not entered and when the number entered is not an integer when entering the exponent!

Example input/output:

Enter a base number: abc
You didn't enter a number!

Enter a base number: 3.3
Enter exponent: something
You didn't enter a number!

Enter a base number: 3.3
Enter exponent: 5
3.3^5 = 391.354

Enter a base number: 12
Enter exponent: 2.5
Entered number is not an integer!

This is my code so far:

#include <stdio.h>

int main() {

    double base, result = 1;
    int exp, i;
    
    printf("Enter a base number: ");
    scanf("%lf", &base);

    printf("Enter exponent: ");
    scanf("%d", &exp);

    for (i=1; i<=exp; i  ) {
        result *= base;
    }
    printf("%.2lf^%d = %.2lf", base,exp,result);

    return 0;
}

It calculates the power of n successfully. But how do I add the "You didn't enter a number!" text when the input is wrong. Also, some results should be printed with 3 decimals, some with 6, etc.(depends on the result).

CodePudding user response:

... how do I add the "You didn't enter a number!" text when the input is wrong.

To validate that a line of input is a double:

Do not use scanf() anywhere until you know why it is bad.

Instead, read the line of user input with fgets() which forms a string.

char buf[1024]; // Ample size buffer for very large and tiny precise values.
if (fgets(buf, sizeof buf, stdin)) {
  double x;
  int error_code = validate_double(buf, &x);
  if (error_code == 0) printf("%.17g\n", x);
  else printf("Error %d, invalid double <%s>\n", error_code, buf);
}

Validate with strdod()

int validate_double(const char *buf, double *x) {
  errno = 0;
  char *endptr;
  *x = strtod(buf, &endptr);
  if (buf == endptr) return 1; // Non numeric input

  // First skip over trailing white-space
  while (isspace(((const unsigned char *)endptr)[0])) {
    endptr  ;
  } 
  if (*endptr) return 2; // Junk after numeric input

  if (errno == ERANGE && (*x > 1.0 || *x < -1.0)) { // overflow
    return 0; // or maybe 3 if you want to flag this
  }

  if (errno == ERANGE && (*x <= 1.0 && *x >= -1.0)) { // underflow
    return 0; // or maybe 4 if you want to flag this
  }

  return 0;
}
    

To validate input is an integer, could use strtol() or the above and simply add.

  double expo;
  int error_code = validate_double(buf, &expo);
  if (error_code == 0) {
    if (!(expo >= 0.0 && expo <= INT_MAX && (int)expo == expo)) {
      error_code = 5; // Out of  int range or non-integer.
    }
  }

... some results should be printed with 3 decimals, some with 6, etc.(depends on the result).

Try printing with %g with ample precision. This format does not print trailing precision '0' digits.

printf("%.17g\n", result);

CodePudding user response:

Your exponentiation algorithm is [very] inefficient:

for (i = 1; i <= exp; i  ) {
    result *= base;
}

It is the equivalent of doing multiplication by repetitive addition.

To do it efficiently, do "exponentiation by squaring". See: https://en.wikipedia.org/wiki/Exponentiation_by_squaring

Change your loop to:

for (i = exp; i != 0; i /= 2) {
    if (i % 2)
        result *= base;
    base *= base;
}

Also, look at the xpow function in the second code block of my recent answer: What's the problem in the code which was supposed to print Armstrong numbers up to 999

  • Related