有没有快速的方法来确定 n^n 上的前 k 位数字
我正在编写一个程序,我只需要知道另一个大数字的前 k 个(k 可以是 1-5 之间的任意数字),该大数字可以表示为 n^n,其中 n 是一个非常大的数字。
目前我实际上正在计算 n^n ,然后将其解析为字符串。我想知道是否有更好更快的方法存在。
I am writing a program where I need to know only the first k (k can be anywhere between 1-5) numbers of another big number which can be represented as n^n where n is a very large number.
Currently I am actually calculating n^n and then parsing it as a string. I wonder if there is a better more fast method exists.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有两种可能性。
如果您想要前 k 个前导数字(例如:12345 的前导数字是 1),那么您可以使用以下事实来
计算
n*Log10( n)
,然后10^f
的前 k 位数字就是你的结果。如果您使用双精度,则这适用于在舍入误差开始出现之前达到约 10^10 的数字。例如,对于n = 2^20
、f = 0.57466709...
、10^f = 3.755494...
所以你的前 5 个位数为 37554。对于n = 4
、f = 0.4082...
、10^f = 2.56
所以你的第一个数字是 2。如果你想要前 k 个尾随数字(例如:12345 的尾随数字是 5),那么你可以使用模算术。我会使用平方技巧:
再次以 n=2^20 为例,我们发现
result = 88576
。对于 n=4,我们有factor = 1, 4, 6
和result = 1, 1, 6
,所以答案是 6。There are two possibilities.
If you want the first k leading digits (as in: the leading digit of 12345 is 1), then you can use the fact that
so you compute the fractional part
f
ofn*Log10(n)
, and then the first k digits of10^f
will be your result. This works for numbers up to about 10^10 before round-off errors start kicking in if you use double precision. For example, forn = 2^20
,f = 0.57466709...
,10^f = 3.755494...
so your first 5 digits are 37554. Forn = 4
,f = 0.4082...
,10^f = 2.56
so your first digit is 2.If you want the first k trailing digits (as in: the trailing digit of 12345 is 5), then you can use modular arithmetic. I would use the squaring trick:
Taking n=2^20 as an example again, we find that
result = 88576
. For n=4, we havefactor = 1, 4, 6
andresult = 1, 1, 6
so the answer is 6.如果您指的是最低有效数字或最右边的数字,则可以通过模乘法来完成。它的复杂度为 O(N),并且不需要任何特殊的 bignum 数据类型。
这将打印 611,即 11^11 = 285311670611 的前三位数字。
此实现适用于小于 sqrt(INT_MAX) 的 N 值,该值会有所不同,但在我的机器和语言上它超过 46,000。
此外,如果您的 INT_MAX 小于 (10^k)^2,您可以更改 modularExponentiation 来处理可以适合 int 的任何 N:
如果 O(n) 时间对您来说不够,我们可以利用求幂的性质 A^(2*C) = (A^C)^2,并得到对数效率。
if you mean the least significant or rightmost digits, this can be done with modular multiplication. It's O(N) complexity and doesn't require any special bignum data types.
This will print 611, the first three digits of 11^11 = 285311670611.
This implementation is suitable for values of N less than sqrt(INT_MAX), which will vary but on my machine and language it's over 46,000.
Furthermore, if it so happens that your INT_MAX is less than (10^k)^2, you can change modularExponentiation to handle any N that can fit in an int:
if O(n) time is insufficient for you, we can take advantage of the property of exponentiation that A^(2*C) = (A^C)^2, and get logarithmic efficiency.