阶乘问题

1、题目

image

2、代码

#include <bits/stdc++.h>
using namespace std;

int f(int n)
{
    if(n<=0)
    {
        return 1;
    }
    return n*f(n-1);
}

int main()
{
    int n;
    cin>>n;
    int m = f(n)%1007;
    cout<< m<<endl;
    return 0;
}

这个代码只得了 60 分,Why?

问题还是出现在数据类型上,int可以表示的最大的数为 2147483647,而20的阶乘是** 2192834560**,已经超出了 int 的范围,所以应该修改阶乘函数的返回值类型。

试着在 OJ 系统上将 int 换成了 long,则AC通过。

在本机上运行时,发现返回值是负数,有点迷惑,写了下面的代码来分析。

3、具体分析

#include<bits/stdc++.h>
using namespace std;

long f(int n)
{
    if(n==0)
    {
        return1;
    }

    return n*f(n-1);
}

int main()
{
    int n;
    printf("int 可以表示的最大的数为\n%d\n", INT_MAX);
    printf("long 可以表示的最大的数为\n%ld\n", LONG_MAX);
    printf("long long 可以表示的最大的数为\n%lld\n", LLONG_MAX);
    printf("unsigned long long 可以表示的最大的数为\n%llu\n", ULLONG_MAX);
    printf("你要计算前几个数?(q to quit):\n");
    while(scanf("%d",&n)==1)
    {
        if(n <0)
        printf("无效的数字\n");
        else
        {
            printf("前%d 个数的阶乘是\n%lld\n", n, f(n));
        }
    }
    return0;
}

以上程序的运行输出如下:

1.  int可以表示的最大的数为
2.  2147483647
3.  long可以表示的最大的数为
4.  2147483647
5.  longlong可以表示的最大的数为
6.  9223372036854775807
7.  unsignedlonglong可以表示的最大的数为
8.  18446744073709551615
9.  你要计算前几个数?(q to quit):
10.  20
11.  前20个数的阶乘是
12.  2192834560

4、问题分析

也就是说,我本机的编译器中,int 和 long 的数据范围是一样的,而在我使用的 oj 系统上是不一样的,因此此处保险的策略是将阶乘函数的返回值写成 long long。****下面进行了一点点深入的分析。

** long 类型的长度**

数据类型的字节数应该是由CPU决定的。

对于C语言的int,无论是32位编译器还是64位,都是4个字节。

long类型在32位编译器是4个字节,64位是8个字节。

宏LONG_MAX和LLONG_MAX均存在于头文件limits.h中,分别表示long intlong long int类型的最大值。

Dev C++ 的安装目录中,也能找到 limits.h,内容如下:

#define PATH_MAX 260
#define CHAR_BIT 8
#define SCHAR_MIN (-128)
#define SCHAR_MAX 127
#define UCHAR_MAX 0xff
#define CHAR_MIN SCHAR_MIN
#define CHAR_MAX SCHAR_MAX
#define MB_LEN_MAX 5
#define SHRT_MIN (-32768)
#define SHRT_MAX 32767
#define USHRT_MAX 0xffffU
#define INT_MIN (-2147483647-1)
#define INT_MAX 2147483647
#define UINT_MAX 0xffffffffU
#define LONG_MIN (-2147483647L-1)
#define LONG_MAX 2147483647L
#define ULONG_MAX 0xffffffffUL
#define LLONG_MAX 9223372036854775807ll
#define LLONG_MIN (-9223372036854775807ll-1)
#define ULLONG_MAX 0xffffffffffffffffull
#define _I8_MIN (-127-1)
#define _I8_MAX 127
#define _UI8_MAX 0xffu
#define _I16_MIN (-32767-1)
#define _I16_MAX 32767
#define _UI16_MAX 0xffffu
#define _I32_MIN (-2147483647-1)
#define _I32_MAX 2147483647
#define _UI32_MAX 0xffffffffu
#if defined(__GNUC__)
#undef LONG_LONG_MAX
#define LONG_LONG_MAX 9223372036854775807ll
#undef LONG_LONG_MIN
#define LONG_LONG_MIN (-LONG_LONG_MAX-1)
#undef ULONG_LONG_MAX`
#define ULONG_LONG_MAX (2ull* LONG_LONG_MAX +1ull)
#endif
#define _I64_MIN (-9223372036854775807ll-1)
#define _I64_MAX 9223372036854775807ll
#define _UI64_MAX 0xffffffffffffffffull

也就是说,Dev C++ 是 32 位编译器。

5\数据类型范围速查表

char             -128 ~ +127        (1 Byte)    
short             -32767 ~ + 32768    (2 Bytes)   **3*10^4**
unsigned short     0 ~ 65536        (2 Bytes)   ** 6*10^4**
int             -2147483648 ~ +2147483647   (4 Bytes)   ** 2*10^9**
unsigned int         0 ~ 4294967295    (4 Bytes)       **4*10^9**
long == int
long long         -9223372036854775808 ~ +9223372036854775807    (8 Bytes)     ** 9*10^18**
double         **1.7 * 10^308  **      (8 Bytes)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。