1

这个函数(为了方便而用 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;
}

如果有一种通用的、万无一失的技术可以将这种循环转换为算术,那将是一个理想的答案。如果做不到这一点,这个实例的解决方案就可以了。

4

2 回答 2

2

首先,为简单起见:

to = from + len - 1

我认为对于每个“部分”,它可以分为 3 个方程。那是:

  • 答:00xD800 - 1
  • B:0xD8000xDFFF
  • C:0xDFFF + 1到无穷大

AC部分“价值”2,B价值 1。除非我误解了您的代码——只有 2 个部分吗?

因此,将每个部分的值乘以属于它的范围的长度:

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

假设min是一个返回较小参数的函数:范围是from到节的末尾,或者len,以较短者为准”。范围是(结束 - 开始 + 1)。

乙: 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.

我不知道这对计算机是否更有效。不过,这对我的大脑来说肯定效率较低。

于 2014-01-24T20:29:35.727 回答
0

通过结合 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);

我已经对其进行了详尽的测试,以始终产生与原始结果相同的结果,并且清楚地显示了在一般情况下如何做这种事情。

于 2014-01-25T04:07:33.860 回答