C语言 为什么在计算阶乘时会出现问题?[关闭]

eagi6jfj  于 2023-06-21  发布在  其他
关注(0)|答案(2)|浏览(105)

编辑问题以包括desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答这个问题。
6天前关闭
Improve this question
这是我的代码,我试图建立一个科学计算器:

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

// define constants for menu options
#define ARITHMETIC 'j'
#define TRIGONOMETRY 'k'
#define ADD 'a'
#define SUBTRACT 'b'
#define MULTIPLY 'c'
#define DIVIDE 'd'
#define SIN 'i'
#define COS 'c'
#define TAN 't'
#define POW 'm'
#define LOG 'e'
#define SQRT 's'
#define FACT 'g'
#define PREVIOUS 'r'
#define EXIT 'x'

// declare a function for factorial using recursion
long int factorial(int n);

int main()
{
    // declare variables for user input and calculation result
    char choice; // store the user's choice of operation
    double x, y, result; // store two numbers for arithmetic operations and the final result of any calculation
    int n; // store a number for factorial calculation

    // print a welcome message
    printf("Welcome to the scientific calculator\n");

    // repeat until the user chooses to exit
    do {
        // print the main menu options
        printf("------------------------------------------------Calculator-----------------------------------------------------\n");
        printf("arithmeticoperations<%c> trigonometryoperations<%c> exit<%c>\n", ARITHMETIC, TRIGONOMETRY, EXIT);

        // get the user's choice of operation
        scanf(" %c", &choice);

        // handle different choices of operations using switch statement
        switch (choice) {
            case ARITHMETIC:
                // print the arithmetic menu options
                printf("add<%c> subtract<%c> multiply<%c> divide<%c> previous_menu<%c> exit<%c>\n", ADD, SUBTRACT, MULTIPLY, DIVIDE, PREVIOUS, EXIT);

                // get the user's choice of operation
                scanf(" %c", &choice);

                // handle different choices of operations using switch statement
                switch (choice) {
                    case ADD:
                        // get two numbers from user and calculate their sum
                        printf("Enter two numbers: ");
                        scanf("%lf %lf", &x, &y);
                        result = x + y;
                        printf("%.2lf + %.2lf = %.2lf\n", x, y, result);
                        break;
                    case SUBTRACT:
                        // get two numbers from user and calculate their difference
                        printf("Enter two numbers: ");
                        scanf("%lf %lf", &x, &y);
                        result = x - y;
                        printf("%.2lf - %.2lf = %.2lf\n", x, y, result);
                        break;
                    case MULTIPLY:
                        // get two numbers from user and calculate their product
                        printf("Enter two numbers: ");
                        scanf("%lf %lf", &x, &y);
                        result = x * y;
                        printf("%.2lf * %.2lf = %.2lf\n", x, y, result);
                        break;
                    case DIVIDE:
                        // get two numbers from user and calculate their quotient
                        printf("Enter two numbers: ");
                        scanf("%lf %lf", &x, &y);
                        // check if the second number is zero
                        if (y == 0) {
                            // print an error message and skip the calculation
                            printf("Cannot divide by zero\n");
                            break;
                        }
                        result = x / y;
                        printf("%.2lf / %.2lf = %.2lf\n", x, y, result);
                        break;
                    case PREVIOUS:
                        // go back to the previous menu
                        break;
                    case EXIT:
                        // print a goodbye message and exit the loop
                        printf("Thank you for using the scientific calculator\n");
                        break;
                    default:
                        // print an error message for invalid choice
                        printf("Invalid option\n");
                }
                break;
            case TRIGONOMETRY:
                // print the trigonometry menu options
                printf("sin<%c> cos<%c> tan<%c> pow<%c> log<%c> sqrt<%c> n!<%c> previous_menu<%c> exit<%c>\n", SIN, COS, TAN, POW, LOG, SQRT, FACT, PREVIOUS, EXIT);

                // get the user's choice of operation
                scanf(" %c", &choice);

                // handle different choices of operations using switch statement
                switch (choice) {
                    case SIN:
                        // get a number from user and calculate its sine
                        printf("Enter a number: ");
                        scanf("%lf", &x);
                        result = sin(x);
                        printf("sin(%.2lf) = %.2lf\n", x, result);
                        break;
                    case COS:
                        // get a number from user and calculate its cosine
                        printf("Enter a number: ");
                        scanf("%lf", &x);
                        result = cos(x);
                        printf("cos(%.2lf) = %.2lf\n", x, result);
                        break;
                    case TAN:
                        // get a number from user and calculate its tangent
                        printf("Enter a number: ");
                        scanf("%lf", &x);
                        // check if the number is a multiple of pi/2
                        if (fmod(x, M_PI / 2) == 0) {
                            // print an error message and skip the calculation
                            printf("Cannot take tangent of multiples of pi/2\n");
                            break;
                        }
                        result = tan(x);
                        printf("tan(%.2lf) = %.2lf\n", x, result);
                        break;
                    case POW:
                        // get two numbers from user and calculate their power
                        printf("Enter two numbers: ");
                        scanf("%lf %lf", &x, &y);
                        result = pow(x, y);
                        printf("%.2lf ^ %.2lf = %.2lf\n", x, y, result);
                        break;
                    case LOG:
                        // get a number from user and calculate its natural logarithm
                        printf("Enter a number: ");
                        scanf("%lf", &x);
                        // check if the number is positive
                        if (x <= 0) {
                            // print an error message and skip the calculation
                            printf("Cannot take logarithm of zero or negative numbers\n");
                            break;
                        } else{
                        result = log10(x);
                        printf("log(%.2lf) = %.2lf\n", x, result);}
                        break;
                    case SQRT:
                        // get a number from user and calculate its square root
                        printf("Enter a number: ");
                        scanf("%lf", &x);
                        // check if the number is non-negative
                        if (x < 0) {
                            // print an error message and skip the calculation
                            printf("Cannot take square root of negative numbers\n");
                            break;
                        }else{
                        result = sqrt(x);
                        printf("sqrt(%.2lf) = %.2lf\n", x, result);}
                        break;
                    case FACT:
                        // get a number from user and calculate its factorial using factorial function
                        printf("Enter a number: ");
                        scanf("%d", &n);
                        // check if the number is non-negative
                        if (n < 0) {
                            // print an error message and skip the calculation
                            printf("Cannot take factorial of negative numbers\n");
                            break;
                        }else{
                        result = factorial(n);
                        printf("%d! = %ld\n", n, result);}
                        break;
                    case PREVIOUS:
                        // go back to the previous menu
                        break;
                    case EXIT:
                        // print a goodbye message and exit the loop
                        printf("Thank you for using the scientific calculator\n");
                        break;
                    default:
                        // print an error message for invalid choice
                        printf("Invalid option\n");
                }
                break;
            case EXIT:
                // print a goodbye message and exit the loop
                printf("Thank you for using the scientific calculator\n");
                break;
            default:
                // print an error message for invalid choice
                printf("Invalid option\n");
        }
    } while (choice != EXIT);

    return 0;
}

// define a function for factorial using recursion
long int factorial(int n) {
    // base case: if n is zero or one, return one
    if (n == 0 || n == 1) {
        return 1;
    }
    // recursive case: if n is greater than one, return n times factorial of n-1
    else {
        return n * factorial(n - 1);
    }
}

一切似乎都是正确的,一切都在运转。但是当用户试图计算数字的阶乘时。它会打印出错误的号码。这个功能有什么不好。
我试过聊天GPT它也说它是正确的。和Bing AI一样。我也在多个编译器和设备上尝试过,仍然是同样的问题。

bmvo0sr5

bmvo0sr51#

printf("%d! = %ld\n", n, result);中,对应于%ld的参数应该具有long int类型,但result具有double类型,导致 undefined behavior
%ld更改为%f可以解决这个问题,但最好将调用factorial(n)的结果存储到long int类型的变量中:

long int lresult; // storage for result of factorial
lresult = factorial(n);
                        printf("%d! = %ld\n", n, lresult);}

如果long int是32位整数,则这应该适用于n12;如果long int是64位整数,则这应该适用于n20。
64位无符号整数将支持n的值,最大值为21。由于unsigned long long int至少为64位宽,因此可以将factorial()函数更改为返回unsigned long long int

// define a function for factorial using recursion
unsigned long long int factorial(unsigned int n) {
    // base case: if n is zero or one, return one
    if (n == 0 || n == 1) {
        return 1;
    }
    // recursive case: if n is greater than one, return n times factorial of n-1
    else {
        return n * factorial(n - 1);
    }
}

然后:

unsigned long long int ullresult; // storage for result of factorial
ullresult = factorial(n);
                        printf("%d! = %llu\n", n, ullresult);}
h9a6wy2h

h9a6wy2h2#

只需将“%ld”替换为“%.2lf”即可打印阶乘结果,就像您用于显示所有其他结果一样。
printf(“%d!= %.2lf\n”,n,result);
%ld,%d只应用于十进制整数。
修正了编译器链接下面的问题,现在它对我有效了。https://www.programiz.com/cpp-programming/online-compiler/

相关问题