Это отвечает только на половину вашего вопроса (почему это так работает).
Вы получите следующий результат: 21! mod 2^64
. Это связано с тем, что вы используете 64-битную систему, а 21!
больше, чем максимальное число, которое может быть сохранено как целое число без знака в 64-битном формате.
Все факториалы, которые вы вычисляете для значений, больших или равных 21
, неверны; они не могут быть представлены 64-битными целыми числами, потому что они длиннее.
Вы можете попробовать использовать unsigned long long
в качестве типа значений, возвращаемых функцией fact()
(и перейти на строку формата printf()
%lu
с %llu
); это может помочь, но это зависит от некоторых факторов. Например, это не помогает в моей архитектуре.
Вы можете узнать, может ли это вам помочь, проверив значение, возвращаемое sizeof(unsigned long long)
. Если 8
, то вам не повезло. 20
— это наибольшее число, которое вы можете вычислить факториалом в этой системе.
Если вашей целью является вычисление факториалов, вам нужно использовать библиотеку, которая знает, как обрабатывать большие числа. Однако, если вам нужны факториалы для других вычислений (например, для комбинаций), вы можете попробовать избегайте создания больших чисел и найдите способ сопоставить каждое умножение с делением. Таким образом, величина используемых вами чисел находится в пределах 64-битных целых чисел, и вы можете пойти дальше, чем 21
.
Или вы можете использовать double
вместо целых чисел, и вы снова в деле, но с потерей точности. Большие числа с плавающей запятой правильно сохраняют величину числа и его первые цифры. Последние цифры теряются.
Я не очень много программировал на C/C++ в последнее время, я не могу порекомендовать вам библиотеку, которая может помочь вам выполнять вычисления с большими числами :-(
person
axiac
schedule
09.03.2016
ULONG_MAX
в вашей системе? - person too honest for this site   schedule 09.03.2016unsigned long long
. - person Spikatrix   schedule 09.03.2016unsigned long long
недостаточно (по крайней мере, если компилятор использует минимальный размер, установленный стандартом) - person Garf365   schedule 09.03.2016ULONG_MAX
— это макрос, который содержит максимальное значение, которое может быть сохранено внутриunsigned long
. - person Garf365   schedule 09.03.2016unsigned long long
может хранить больше значений, чемunsigned long
. - person Spikatrix   schedule 09.03.2016long long
не должен быть длиннее 64 бит. На компьютере OPlong
уже 64-битный.int
, с другой стороны, не должен быть длиннее 32 бит в любой системе. - person vll   schedule 09.03.2016unsigned long
должно быть не менее 32-битным,unsigned long long
должно быть не менее 64-битным иsizeof(unsigned long long) >= sizeof(unsigned long)
. Так что не исключено, чтоunsigned long long
иunsigned long
имеют одинаковый размер и поэтому хранят одинаковые значения. - person Garf365   schedule 09.03.2016int
вполне может иметь 1024 бита. - person too honest for this site   schedule 09.03.2016