对于一些非常大的k和j(两者都是几百万的数量级),我需要计算0 ^ j,1 ^ j,...,k ^ j。我正在使用GMP来处理大整数(是的,我需要整数,因为我需要全精度)。现在,我想,一旦我完成了计算n ^ j的努力,是不是有办法加速(n + 1)^ j的计算,而不是从头开始?
以下是我目前用于计算功率的算法:
mpz_class pow(unsigned long int b, unsigned long int e)
{
mpz_class res = 1;
mpz_class m = b;
while(e)
{
if(e & 1)
{
res *= m;
}
e >>= 1;
m *= m;
}
return res;
}
正如您所看到的,每次我从头开始,都需要花费很多时间。
答案 0 :(得分:1)
您可能希望使用(n + 1)^ j的二项式展开为n ^ j + j n ^(j-1)+ j (j-1)/ 2 * n ^(j-2)+ ... + 1并且记忆已经计算的较低功率并且通过加法重新使用它们来在O(n)时间内计算(n + 1)^ j。如果在添加每个项时逐步计算系数j,j *(j-1)/ 2,...,也可以在O(n)中完成。
答案 1 :(得分:1)
要计算n^j
,为什么不找到n
的至少一个因素,比如k
执行n^j = k^j * (n/k)^j
?在计算n^j
时,k^j
和(n/k)^j
都应该是已知的。
但上述O(sqrt(n))
的上述时间可能为n
。正如您在上面的代码中所提到的,我们在n^j
时间内O(log(j))
独立计算了n
。
所以你可以混合使用上面哪个更大:
如果log(j)
远小于n^j
,请按分解计算n^j
。
每当{(2*n)^j, (3*n)^j, ..., ((n-1)*n)^j, n * n^j}
知道计算n
并将其保存在查找表中时。
如果log(j)
大于n
并且无法进行如上所述的就绪计算,请使用对数方法,然后计算上述其他相关功能。
如果2
是j
的纯粹力量(可能为Exponentiation by Squaring),请通过移位计算n
幂并计算相关总和。
如果import Vue from 'vue'
import Zoom from 'src/components/Zoom'
import $ from 'jquery'
/* eslint-disable no-unused-vars */
/**
* get template for wrapper Vue object make Vue with Zoom component and that template
* @param wrapperTemplate
* @returns {Vue$2}
*/
const makeWrapper = (wrapperTemplate = '<div><zoom ref="component"></zoom></div>') => {
return new Vue({
template: wrapperTemplate,
components: {Zoom}
})
}
const startWrapperWidth = 1093
const startWrapperHeight = 289
const startImageWidth = 1696
const startImageHeight = 949
const padding = 15
/**
* gets vueWrapper and return component from it
* @param vueWrapper
* @param useOffset
* @returns {'Zoom component'}
*/
const setSizesForComponent = (vueWrapper) => {
vueWrapper.$mount()
var cmp = vueWrapper.$refs.component
var $elWrapper = $(cmp.$el)
var $elImage = $elWrapper.find(cmp.selectors.image)
$elWrapper.width(startWrapperWidth)
$elWrapper.height(startWrapperHeight)
$elWrapper.css({padding: padding})
$elImage.width(startImageWidth)
$elImage.height(startImageHeight)
cmp.calculateSizesAndProportions()
return cmp
}
describe('onZoom method (run on mousemove)', () => {
sinon.spy(Zoom.methods, 'onZoom')
let vueWrapper = makeWrapper()
let cmp = setSizesForComponent(vueWrapper)
let e = document.createEvent('HTMLEvents')
e.initEvent('mousemove', true, true)
e.pageX = 150
e.pageY = 250
let callsOnZoomBeforeMousemove = Zoom.methods.onZoom.callCount
cmp.$el.dispatchEvent(e)
describe('left and top computed props', () => {
it('left', () => {
expect(cmp.left).is.equal(-74)
})
it('top', () => {
expect(cmp.top).is.equal(-536)
})
})
})
是偶数(再次计算常数时间),请使用分解方法并计算相关产品。
以上应该会很快。例如,偶数的识别本身应该将一半的功率计算转换为乘法。可能会有更多关于因子分解的拇指规则可以进一步减少计算(特别是对于3,7等的可分性)