2013-06-18 22 views
0

鑑於兩個浮點值zoomAmountzoomFactor最近的整數次冪,我需要計算newZoomAmount使得:回合下來浮動

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

任何整數i。我可以很容易地循環查看錶格中的值或二進制搜索以找到答案。但是:有沒有一種封閉的形式來實現這一目標?


動機:該zoomFactor是2 1.148698354997035,使得事件的每個5 「放大」 導致〜兩種增加準確的功率。當縮放圖表以適合屏幕時,我希望縮放級別成爲這些刻度中的一個,以便縮小最終落在「基本」1.0縮放級別上。

+0

標籤爲Qt,因爲這是用來縮放'QGraphicsView',因此我可以使用任何Qt方法,這可以讓它更容易實現。 – Phrogz

回答

4

表示:

A = zoomAmount 
F = zoomFactor 
newA = newZoomAmount 

我們有:

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

和作爲紐瓦< = A,並登錄在非遞減,

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

newZoomAmount = pow(zoomFactor, floor(log(zoomAmount)/log(zoomFactor))); 
+0

你明白了。我編輯了你的答案,總結一下,回到問題的值。 – Phrogz

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);

+0

+1代表重構和重新計算。需要一個'floor()'將'i <= ...'轉換爲'i = ...',但是一個非常簡單的派生。尷尬,我不認爲這樣做。謝謝 :) – Phrogz

1
exponent=log(zoomAmount)/log(zoomFactor); /* zoomFactor^exponent == zoomAmount */ 
newZoomAmount=pow(zoomFactor,floor(exponent)); /* round down exponent */ 
2

基本上,對數。我會忽略這個事實,log的底層實現可能會迭代,因爲你可能不介意。

使用下列內容:

 
zoomFactor = 21/5 
      = 1.148698354997035 
zoomAmount = 2.25 

你需要找到以下的(請注意,我用的比,而不是小於或等於少,看到底爲什麼):

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

通過檢查我們知道(因爲zoomFactor5 == 2zoomFactor6 == 2.297... > 2.25

 
newZoomAmount == 2 
i == 5 

因此,爲了得到當前zoomAmount在指數方面,我們採取:

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

爲了得到一個最低的整數,你應該減1,然後採取了天花板。

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

最後:

 
newZoomAmount = zoomFactornewZoomExponent 

我們使用的減量而不是隻是樓層的天花板上的原因是爲了處理特殊情況下zoomAmountzoomFactor一個完美的電源,在這種情況下

⌊zoomExponent⌋ == zoomExponent 
newZoomAmount == zoomAmount 

我們明顯不想要的。