2012-02-12 51 views
0

可怕的稱號的道歉。我花了10分鐘試圖用一句話解釋這一點,但失敗了。從等級堆棧獲得相對比例的數學運算

雖然提示此問題的應用程序是在Java(Android)中,但我認爲它非常通用,適用於任何語言。僞代碼(或簡單的英文)回覆是受歡迎的。我不確定是否應該標記所有常用語言,但這似乎有點垃圾。

我的實際需求比稍後的一些示例稍微簡單一些,但我會盡量簡單明瞭地介紹這個想法。

說我有5 「圖像的水平」,每一級是雙前一級的大小:

  • 級別1 = 100像素正方形
  • 級別2 = 200像素正方形
  • 3級= 400像素正方形
  • 級別4 = 800像素正方形
  • 水平5 = 1600像素正方形

這些圖像層次都顯示相同的東西,但具有不同程度的細節(最小的圖像只顯示主要特徵;最大的圖像顯示細節)。

假設我們從不想縮放較大的圖像以避免失真,並且應該只對圖像執行變形以使其變小,目標是使用具有最小縮放量的最大合適圖像。

假設用戶處於3級(400px)級別,並執行1.8級縮放操作。新的尺寸應該是(1.8 * 400 = 720),這意味着我應該顯示4級(800px),縮放到0.9(800 * 0.9 = 720)。

另一個例子 - 一個用戶在2級,可以擴展到5.2。大小將是(5.2 * 200 = 1040)。因此顯示5級,縮放到0.65(1600 * 0.65 = 1040)。

知道關卡的大小,邏輯非常簡單。

  1. 取當前級別的大小,乘以用戶級別。致電此newSize
  2. 查找大小大於該數字的最低級別。撥打targetLevel
  3. newSize除以targetLevel的大小。這是相對規模。

現在讓我們假設我實際上並不知道圖像的實際尺寸,也沒有辦法找到它們,也許它們不是真的應該是它們的大小(儘管它們總是會重現比以前的水平翻一番),並且可能有任何數量的水平。

僅使用當前級別和用戶定義的比例值,返回適當的目標級別和相對(新)規模時涉及哪些數學或邏輯?

更多的例子...

  • 用戶在5級量表爲0.2。新的水平應該是3,新的水平應該是0。8
  • 級別1的用戶縮放至3.6。新的等級應該是3,新的等級應該是0.9
  • 等級1的用戶可以縮放到5.0。新的級別應該是4,新的級別應該是0.625
  • 級別2的用戶可以擴展到5.0。新的等級應該是5,新的等級應該是0.625
  • 等級3的用戶等級爲3.0。新的級別應該是5,新的級別應該是0.75
  • 級別4的用戶縮放到0.3。新的等級應該是3,新的等級應該是0.6
  • 等級4的用戶等級爲1.6。新級別應爲5,新級別應爲0.8
  • 級別4的用戶級別爲0.6。新的水平應該是4,新增規模應爲0.6 [1]

[1]可能是明顯的,但任何小於1但大於0.5會保持不變

TYIA

回答

3

你「水平」可以通過下面的指數函數定義(與你的等級從1開始):
level(x) = baseSize * 2<sup>x-1</sup>

爲簡單起見,我們假設你有s<sub>x</sub>(規模)和level(x)和你想找到level(y)

看到如何level(x)定義,你可以看到,

2<sup>a</sup> * level(x) = level(x+a)

但是,你的規模是不是在2一樣,整齊的權力賦予,所以你可以用下面的(四捨五入爲找到按照您的情況):

⌈log<sub>2</sub>(s<sub>x</sub>)⌉ = a

這意味着y = x + ⌈log<sub>2</sub>(s<sub>x</sub>)⌉level(y) = 2<sup>⌈log<sub>2</sub>(s<sub>x</sub>)⌉</sup> * level(x)

現在我們有了新的水平,我們有以下的公式:
s<sub>x</sub> * level(x) = s<sub>y</sub> * level(y)<br>
s<sub>x</sub> * baseSize * 2<sup>x-1</sup> = s<sub>y</sub> * baseSize * 2<sup>y-1</sup>
s<sub>x</sub> * 2<sup>x-1</sup>/2<sup>y-1</sup> = s<sub>y</sub>
s<sub>x</sub> * 2<sup>x-y</sup> = s<sub>y</sub>

/編輯
是的,這就是2 X-1手段。

  • 小號 X只是一些常數隨x去(在這種情況下,它是你的規模),同樣,S ÿ是一些常數,其中y去。

  • 只有最高位(⌈⌈)的奇怪方括號只是最高限制功能(Math.ceil)。

  • 對數是取冪的倒數。對數定義如下:如果a c = b,則記錄 a(b)= c。例如,日誌(8)= 3,因爲2 = 8還有其他問題嗎?

/Java示例

int newLevel = oldLevel + (int) Math.ceil(Math.log(oldScale)/Math.log(2)); 
double newScale = oldScale * Math.pow(2, oldLevel - newLevel);

我們必須使用change of base公式對數,因爲Math僅提供logelog10。爲Math.log(2)創建一個常量可能是值得的,所以你不會重新計算它。

+0

貼過你 - 對不起,沒看到,當我開始寫... ...消化 – momo 2012-02-12 05:28:00

+0

我強烈懷疑這是正確的答案,但說實話這是在我頭上的方式 - 我甚至不清楚符號。你有什麼機會可以解釋,好像我在9年級退學? TYIA – momo 2012-02-12 05:57:41

+0

@Big MoMo將方程改爲圖像使其更清晰。哪些部分讓你感到困惑?老實說,我很樂意解釋 – Jeffrey 2012-02-12 05:58:39

1

這個簡單的matching game使用enum Game來指定遊戲的四個級別所需的常量。通過覆蓋toString()(並略微違反常量的情況約定),可以使用Game.values()直接填充水平選擇gameCombo。更改級別只需要更換組件並在封裝的Container上調用validate()

+0

這與數學幾乎沒有關係,但一旦您獲得了縮放因子,它可能會很有用。 – trashgod 2012-02-12 05:32:14

+0

感謝您的鏈接 - 我實際上並沒有在一款遊戲上工作,但我一定會深入瞭解它,看看您是如何處理水平的,一旦我完成了這個特定的部分。 – momo 2012-02-12 06:52:41

0

那麼遠,

public static void getZoom(int currentLevel, double userScale){ 
     double ns = (1 << (currentLevel - 1)) * userScale; 
     int newLevel = 1; 
     int ts = 1; 
     while(ts < ns){ 
      ts <<= 1; 
      newLevel++; 
     } 
     double newScale = ns/ts; 
     System.out.println(newLevel + ", " + newScale); 
    }