簡體   English   中英

將此循環簡化為方程式

[英]Reduce this loop to an equation

此函數(為方便起見,用C語言編寫,但這對問題並不重要)決定了數組的大小。 我敢肯定它可以轉換為if-else鏈,甚至可以轉換為方程式,但是我不夠聰明,無法看到如何轉換。 (我試圖寫下明顯的if-else鏈,但在某些情況下陷入困境。)

// 0 <= from <= 0x10FFFF
// 1 <= len <= 0x10FFFF
unsigned int size_for_block(unsigned int from, unsigned int len)
{
  unsigned int size = 0;
  for (unsigned int i = 0; i < len; i++) {
    unsigned int point = from + i;
    if (0xD800 <= point && point <= 0xDFFF)
      ;
    else if (point <= 0xFFFF)
      size += 1;
    else
      size += 2;
  }
  return size;
}

如果存在將這種循環轉換為算術的通用,防呆子技術,那將是一個理想的答案。 如果失敗,此實例的解決方案就可以了。

首先,為簡單起見:

to = from + len - 1

我認為對於每個“部分”,它可以分為3個方程式。 那是:

  • A: 00xD800 - 1
  • B: 0xD8000xDFFF
  • C: 0xDFFF + 1到無窮大

AC部分的價值為2, B部分的價值為1。除非我誤解了您的代碼,否則只有2個部分嗎?

因此,將每個部分的值乘以該范圍內的范圍的長度:

答: if (from < 0xD800) size += 2 * min((0xD800 - 1) - from + 1, len)

假設min是一個返回其較少參數的函數:范圍是from到本節的末尾,或len ,以較短者為准” 范圍是(結束-開始+ 1)。

B: if (to > 0xD800) size += 1 * min(0xDFFF - 0xD800 + 1, to - D800 + 1)

該邏輯是在這里類似:“完整的部分,或部分的開始to孰短”。

C: if (to > 0xDFFF + 1) size += 2 * (to - (0xDFFF + 1) + 1)

這是簡單的,因為沒有終點:從一開始就只算to

我不知道這對計算機是否更有效。 但是,對於我的大腦而言,這肯定效率較低。

通過結合nmclean的答案和該問題的概念,我現在有了:

function overlap(min1, max1, min2, max2) {
  return Math.max(0, Math.min(max1, max2) - Math.max(min1, min2));
}
size = (overlap(from, from+len, 0x000000, 0x00D800) +
        overlap(from, from+len, 0x00E000, 0x010000) +
        overlap(from, from+len, 0x010000, 0x110000)*2);

我經過詳盡的測試,總是能得到與原始結果相同的結果,並且清楚地表明了在一般情況下如何進行此類操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM