我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不起作用,发生了啥?

Posted

技术标签:

【中文标题】我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不起作用,发生了啥?【英文标题】:I've made a program in C that takes two inputs, x and n, and raises x to the power of n. 10^10 doesn't work, what happened?我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不起作用,发生了什么? 【发布时间】:2020-06-24 00:03:42 【问题描述】:

我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不行,怎么回事?

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

float isEven(int n)

    return n % 2 == 0;


float isOdd(int n)

    return !isEven(n);


float power(int x, int n)

    // base case
    if (n == 0)
    
        return 1;
    
    // recursive case: n is negative
    else if (n < 0)
    
        return (1 / power(x, -n));
    
    // recursive case: n is odd
    else if (isOdd(n))
    
        return x * power(x, n-1);
    
    // recursive case: n is positive and even
    else if (isEven(n))
    
        int y = power(x, n/2);
        return y * y;
    
    
    return true;


int displayPower(int x, int n)

    printf("%d to the %d is %f", x, n, power(x, n));
    return true;


int main(void)

    int x = 0;
    printf("What will be the base number?");
    scanf("%d", &x);
    
    int n = 0;
    printf("What will be the exponent?");
    scanf("%d", &n);
    
    displayPower(x, n);

例如,这里有一对有效的输入:

./exponentRecursion 
What will be the base number?10
What will be the exponent?9
10 to the 9 is 1000000000.000000

但这就是我用 10^10 得到的:

./exponentRecursion 
What will be the base number?10
What will be the exponent?10
10 to the 10 is 1410065408.000000

为什么会写出这么奇怪的数字?

顺便说一句,10^11 返回 141006540​​80.000000,正好是上面的十倍。

也许我使用的数据类型有一些“限制”?我不确定。

【问题讨论】:

您正在以奇怪且不那么奇妙的方式混合floats 和ints。您首先需要确定是在计算 float 还是和 int,然后在所有计算中始终使用正确的类型。 int y = power(x, n/2); 这会将浮点数转换为整数。然后你 return y * y; 这是一个整数乘法。但整数乘法不能高达 10^10。它的最大值约为 2 * 10^9。 不可能!?所以有一个限度。正如 dbush 建议的那样,双打会更好。 【参考方案1】:

您的变量 x 是 int 类型。最常见的内部表示是 32 位。这是一个有符号二进制数,因此只有 31 位可用于表示幅度,通常的最大正 int 值为 2^31 - 1 = 2,147,483,647。任何更大的都会溢出,给出更小的量级并且可能是负号。

对于更大的范围,您可以将 x 的类型更改为 long long(通常为 64 位 - 约 18 位)或double(通常为 64 位,51 位精度约 15 位)。

(警告:许多实现对intlong 使用相同的表示,因此使用long 可能不会有所改进。)

【讨论】:

【参考方案2】:

float 仅对大约 7 位十进制数字具有足够的精度。任何位数多于该数字的数字都只是一个近似值。

如果您切换到double,您将获得大约 16 位的精度。

【讨论】:

【参考方案3】:

当您开始使用 C 中的 基本 数据类型处理大数时,您可能会遇到麻烦。

整数类型的值范围有限(例如 32 位无符号整数的 4x109)。浮点类型具有更大的范围(尽管不是无限的)但精度有限。例如,IEEE754 双精度可以在 +/-10308

范围内为您提供大约 16 个十进制数字的精度

要恢复这两个方面,您需要使用某种 bignum 库,例如 MPIR。

【讨论】:

【参考方案4】:

如果您在 C 程序中混合不同的数据类型,编译器会执行几种隐式转换。由于编译器的工作方式有严格的规则,因此您可以准确地弄清楚您的程序会发生什么以及为什么。

由于我不知道所有这些强制转换规则,我做了以下事情:估计最大结果所需的最大精度。然后将过程中的每个变量和函数显式转换为这个精度,即使没有必要。通常这会像解决方法一样工作。

【讨论】:

以上是关于我用 C 语言编写了一个程序,它接受两个输入,x 和 n,并将 x 提高到 n 次方。 10^10 不起作用,发生了啥?的主要内容,如果未能解决你的问题,请参考以下文章

用C语言编写程序实现两个整数交换值

Win10用DEV-C++纯C编写运行结果没出错但结果不对

命令行参数中 * 的问题

c语言简单求和,编写程序:输入两个数,求两个数的和

Python语言编写程序,将两个整数a和b合并成一个整数放到c里面,并打印出来?

用C语言编写程序,如何输入两个整数,并求和。