0

Given two floating point values zoomAmount and zoomFactor, I need to calculate a newZoomAmount such that:

(newZoomAmount <= zoomAmount) && (newZoomAmount == pow( zoomFactor, i ))

for any integer i. I can easily loop through the values or binary search through a table to find the answer. However: is there a closed form to accomplish this?


Motivation: The zoomFactor is 2⅕</sup> ≅ 1.148698354997035, so that each 5 "zoom in" events result in ~exactly a power of two increase. When zooming a diagram to fit on screen I want the zoom level to be one of these notches so that zooming out eventually lands exactly on the 'base' 1.0 zoom level.

4

4 回答 4

4

表示:

A = zoomAmount
F = zoomFactor
newA = newZoomAmount

我们有:

newA = pow(F, i)
=> log(newA) = i*log(F)
=> i = log(newA)/log(F)

并且作为 newA <= A,并且 log 是非递减的,

i = floor(log(A)/log(F))

newZoomAmount = pow( zoomFactor, floor( log(zoomAmount)/log(zoomFactor) ) );
于 2013-06-18T15:58:46.687 回答
2

基本上,对数。我将忽略可能迭代的底层实现这一事实,log因为您可能不介意。

使用以下内容:

缩放因子 = 2 1/5
           = 1.148698354997035
缩放量 = 2.25

您需要找到以下内容(请注意,我使用小于而不是小于或等于,原因见结尾):

(newZoomAmount < 2.25) && (newZoomAmount == 2 i/5 )

通过检查,我们知道(因为和)zoomFactor5 == 2zoomFactor6 == 2.297... > 2.25

newZoomAmount == 2
我 == 5

因此,为了获得zoomAmount指数形式的电流,我们采用:

zoomExponent = log(zoomAmount) / log(zoomFactor)
             = 0.81093... / 0.13862...
             = 5.84962...

要获得下一个最小整数,您应该减去 1,然后取上限。

newZoomExponent = ⌈zoomExponent - 1⌉
                = ⌈4.84962...⌉
                = 5

最后:

newZoomAmount = zoomFactor newZoomExponent

我们使用减量上限而不是下限的原因是为了处理 的zoomAmount完美幂的特殊情况zoomFactor,在这种情况下

⌊zoomExponent⌋ == zoomExponent
newZoomAmount == zoomAmount

这显然是我们不想要的。

于 2013-06-18T16:19:43.273 回答
1
exponent=log(zoomAmount)/log(zoomFactor); /* zoomFactor^exponent == zoomAmount */
newZoomAmount=pow(zoomFactor,floor(exponent)); /* round down exponent */
于 2013-06-18T16:01:45.233 回答
1

只需替换并重新评估:

(newZoomAmount <= zoomAmount) && (newZoomAmount == pow( zoomFactor, i ))=> pow( zoomFactor, i ) <= zoomAmount=> i * ln(zoomFactor) <= ln(zoomAmount)=>i <= ln(zoomAmount) / ln(zoomFactor)这可能会也可能不会比迭代更快。

然后只需分配newZoomAmount = pow( zoomFactor, i );

于 2013-06-18T15:59:14.113 回答