是否有一些数学“最佳”基础可以加速因子计算?

时间:2010-06-19 22:01:02

标签: language-agnostic integer biginteger bignum factorial

是否有一些数学“最佳”基础可以加速因子计算?

背景: 只是为了好玩,我正在实现我自己的bignum库。 ( - :这是我的第一个错误吗?:-)。 我正在试验内部表示和回归测试中使用的各种基础,打印出n阶乘(n!)的精确值(十进制)。

我的bignum库表示整数并进行乘法的方式,时间与内部表示n!中“1”位的总数成正比。 在我的内部表示中使用基数2,4,8,16,2 ^ 8,2 ^ 30等都给出了与任何特定数字完全相同的“1”位总数。

除非我犯了一些错误,否则在基数18中表示的任何给定因子(n!)比在基数10或基数16或基数19中表示的相同值具有更少的“1”位。 因此(原则上),使用基座18将使我的bignum库比使用基础10或一些二进制2 ^ w基础或基础19更快地运行。 我认为这与n这个事实有关!当在基部18中打印时比在基部10或基部16或基部19中打印更短或具有更多“尾随零”或两者。 还有其他一些基础比18基地更好吗? 换一种说法, 有代表n的基数!比基数18更少的“1”位?

这不是“bignum库和素性测试算法的便利基础是什么?”因为我怀疑“使用已知为大因子的整数的最佳基数,有很多因子2和3”不同于“使用没有任何小因子的整数的最佳基数,并且可能是主要”。 ( - :加快阶乘计算 - 可能是以其他类型的计算为代价 - 我的第二个错误?: - )

编辑: 例如:

(decimal) 16! ==
(decimal    ) == 20,922,789,888,000 // uses decimal 14 "1" bits
(dozenal    ) ==  2,41A,B88,000,000 // uses decimal 10 "1" bits
(hexadecimal) ==    130,777,758,000 // uses decimal 18 "1" bits
(octadecimal) ==     5F,8B5,024,000 // uses decimal 14 "1" bits

(我或多或少在右边存储数字,没有逗号,加上一些元数据开销)。 (虽然人们可能会认为“当你增加基数时,你将使用更少的”1“位来表示给定的数字”,或“”当你增加基数时,你将使用更少的非零数字来表示给定的数字“,上面示例显示并非总是如此。)

我将每个数字存储为一个小整数(“int”或“long int”或“byte”)。有没有其他合理的方法来存储数字? 我很确定我的计算机将这些整数存储为二进制 - 每个“1”,“2”,“4”,“8”和“G”数字使用一个“1”位;每个“3”,“5”,“6”,“9”和“A”数字使用两个“1”位;每个“7”和“B”数字使用三个“1”位;每个“F”数字使用四个“1”位等

该值(16!)的十进制和十八进制表示都需要14“1”位。 所以我在之前的计算中犯了一个错误:对于每个n,代表n!在十八进制 总是比在十进制中表示相同的值具有更少的“1”位。 但问题仍然存在:是否还有一些其他“最佳”基础需要最少1位的数据来存储大因子?

有人问:“你如何存储这些数字?” 嗯,这正是我的问题 - 存储n形式数字的最佳方法是什么! ? 我可以在内部使用基数10中的数字,或者一些二次幂,或者基数为18,或者其他一些基数。哪一个最好? 我可以在内部将这些整数存储为1D数字数组,但需要很长的长度来存储所有数字。有没有合理的方式打印100!十进制没有这样的数组?

4 个答案:

答案 0 :(得分:5)

如果您只是尝试优化计算阶乘的运行时间,并且更改基数是您正在更改的唯一参数,那么最佳基数可能包含很小的因子。 60可能是一个合理的选择。如果你想试验,我会尝试形式的各种基础(2 ^ a)(3 ^ b)(5 ^ c)

提高乘法速度可能是性能的最佳方式。您使用什么算法进行乘法? (教科书,Karatsuba,Toom-Cook,FFT,......)

还有其他因素需要考虑。如果您经常将数字转换为十进制数,那么10的幂将使转换尽可能快。

很多(*)年前,我写了一个base-6浮点库专门解决了重复乘法/除2和/或3的问题。但除非你试图解决一个特定的问题,我想你通过优化您的算法将比通过尝试优化阶乘更好地服务。

casevh

(*)我最初说“几年前”直到我记得这个程序在12Mhz 80286上运行了很多天。

答案 1 :(得分:2)

虽然从纯粹的数学观点来看,最佳基础是 e (并且在舍入到最接近的整数-3之后),从计算机上的bignum库的实际角度来看,选择机器字大小为数字系统的基础(2 ^ 32或2 ^ 64)。是的,它是巨大的,但是你的bignum系统的更高抽象层是阻塞点,机器字上的基础计算是快速部分,因此将尽可能多的计算委托给CPU低级指令同时保持自己的工作最小化。

不,这不是一个错误。这是一个非常好的学习练习。

答案 2 :(得分:1)

我不会假装我知道任何数学,所以不要把我的答案视为你可能正在寻找的神圣的“最佳”。如果我必须尽可能快地做阶乘,我会尝试一些近似(类似于斯特林近似)或减少乘法次数,因为乘法是昂贵的操作。如果你用k-base表示数字,你可以在移位的帮助下模拟乘以k。如果选择2基,则所有乘法的一半将是移位。其他乘法是移位和一位开关。如果您的目标是最小化数字表示中“1”的数量,这取决于您所代表的数字。当您增加基数时,您将使用较少的“1”来表示给定的数字,但是您需要为每个订单添加更多位,这意味着更多潜在的“1”。我希望它至少有一点帮助,如果没有,请问,我会尽力回答。

答案 3 :(得分:1)

如果用'“1”位表示数字,那么我建议使用256或65536的基数。换句话说,为了数学的目的,将每个字节/单词设为“数字”。计算机会定期处理这些数字,并为此进行了优化。你的阶乘将是迅速的,其他操作也是如此。

更不用说计算机可以轻松地从类似的基础处理大量的转换。 (押韵无意)