为什么N!当N>=34时停止溢出32位输出变量?

大数字的变量溢出是否有任何限制?一本关于阶乘的 C 书中有一个练习。

我的代码:

#include <stdio.h>

int main(void) {
    unsigned int n, fn, counter;
    //puts("enter nonnegative int");
    //scanf("%u", &n);
    n = 1;
    while (n != 34) {
        fn = n;
        counter = n - 1;
        while (counter > 0) {
            fn *= counter;
            counter--;
        }
        printf("%un", fn);
        n++;
    }
}

注释行用于调试。

此代码打印从 n(1) 到 34 ( 'while(n!=34)')的数字的阶乘,但如果将其增加到 36 之类的值,它将在前 34 个输出后仅打印 0。我知道大部分输出都溢出了,并且对这些大数字的控制非常糟糕。

但是,我想知道导致这些零发生的限制是什么。

回答

你抱怨说

N! 停止溢出 32 位输出变量时 N>=34

这意味着,在 之后34!,结果保持为 0。

嗯,答案是它不会停止溢出。发生的情况是显示的值,即N! / 2^32从 N=34 开始的除法的余数变为 0,并且永远不会改变。

为了理解它是如何发生的,让我们从一个使用十进制数的例子开始。我们将显示 N 的结果!使用只有两位数字的显示器:

阶乘 实际结果 显示结果 笔记
1! 1 01
2! 2 02
3! 6 06
4! 24 24
5! 120 20 溢出!
6! 720 20 溢出!
7! 5040 40 溢出!
8! 40320 20 溢出!
9! 362880 80 溢出!
10! 3628800 00 溢出,显示值为00
11! 39916800 00 溢出,显示值还是00
12! 479001600 00 溢出,显示值还是00
.. .. 00 显示的值将永远为 00

如您所见,显示溢出的5!位置我们还可以注意到结果是 的倍数5*2=10。由于显而易见的原因所有后续的结果将是多5*2=10那么他们将有一个尾随0。
但是,当我们到达10!时一个特殊的条件:结果变成的倍数(5^2)*(2^2)=10^2=100因此,无论是我们事后进行的显示值将始终乘法是00

请记住此信息:当结果开始具有 B^N 的公因数时,我们达到了全 0 条件,其中

  • B 是表示的基础 (10)
  • N 是显示的位数 (2)

所以,在这种情况下, 10^2.


使用二进制(base-2)表示可以完成相同的推理,受 a 的大小限制unsigned int。当结果开始具有 的公因数时,我们将达到全 0 条件B^N = 2^32

结果什么时候会变成 的倍数2^32?让我们计算引入 2 的幂的乘法:

  • 2! 将添加因子 2(总共 2^1)
  • 4! 将增加一个因子 2^2(总共 2^3)
  • 6! 将添加因子 2(总共 2^4)
  • 8! 将增加一个因子 2^3(总共 2^7)
  • 10! 将添加因子 2(总共 2^8)
  • 12! 将增加一个因子 2^2(总共 2^10)
  • 14! 将增加一个因子 2(总共 2^11)
  • 16! 将增加一个因子 2^4(总共 2^15)
  • 18! 将添加因子 2(总共 2^16)
  • 20! 将增加一个因子 2^2(总共 2^18)
  • 22! 将增加一个因子 2(总共 2^19)
  • 24! 将增加一个因子 2^3(总共 2^22)
  • 26! 将添加一个因子 2(总共 2^23)
  • 28! 将增加一个因子 2^2(总共 2^25)
  • 30! 将增加一个因子 2(总共 2^26)
  • 32! 将增加一个因子 2^5(总共 2^31)
  • 34!将添加一个因子 2(总共 2^32)

从现在开始,阶乘将始终是 的倍数2^32,因此显示的结果, 的余数N! / 2^32将始终为 0。


以上是为什么N!当N&gt;=34时停止溢出32位输出变量?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>