我是汇编代码的新手,如果有任何愚蠢的错误,请纠正我.....
给定数字x,您的任务是找到第一个自然数i,其阶乘数可被x整除。
使用mov指令将数字x存储在寄存器%rax中。
最终结果应存储在寄存器%rdi中。
假设选择x不会发生溢出。
我的尝试:
factorial:
pushq %rbp
movq %rsp, %rbp
cmpq $1, %rdi
je if
jmp else
if:
movq $1, %rax
jmp factend
else:
pushq %rdi
subq $1,%rdi
call factorial
popq %rdi
mulq %rdi
jmp factend
factend:
movq %rbp, %rsp
popq %rbp
ret
让我们来研究这个问题:
给定数字x,您的任务是找到第一个自然数i,其阶乘数可被x整除。
也就是说,找到n
这样n! % x == 0
。
如果拆分n!
并x
为他们的主要因素(如像“60 = 2 * 2 * 3 * 5”)你知道,其余的将是零,当所有的主要因素,x
也是首要因素n!
; 这意味着n
必须等于或大于的最大素数x
。
在最坏的情况下,如果x
为素数(只有一个素数),则n
必须等于x
。例如,如果x
为61,n
则将为61。这很重要,因为它n!
很快变大并会溢出(例如,61!
不能容纳64位)。
幸好; 如果n
大于2;n!
与相同(n-1)! * n
; 并且((n-1)! * n) % x
与相同((n-1)! % x) * n) % x
。
换一种说法; 为了使其工作(避免溢出),您可以执行以下操作(无需进行任何计算n!
):
do {
i = i + 1;
remainder = remainder * i;
remainder = remainder % x;
while(remainder != 0);
现在...
假设选择x不会发生溢出。
这实际上是什么意思?
如果询问代码的人认为您将使用我描述的算法;那么它可能意味着x
将小于1 << 64的平方根);因此,如果您使用“更可能发生溢出的算法”(任何会计算的值的算法),那么就会产生溢出,n!
因此必须使用我的算法(或找到更好的算法)。
任何状况之下; 递归是不好的,也是不必要的。