【发布时间】:2012-08-27 05:25:34
【问题描述】:
我在上次采访中被问到这个问题,并再次期待它。面试的对象是为嵌入式系统编程的固件工程师。可用于这些应用的微处理器和微控制器通常不是很强大,更简单的微处理器和微控制器不具备进行浮点计算的能力(内部没有乘法器或除法器)。
那么这个问题的可能答案是什么?定点算术与这个有什么关系(如果有的话)?
是否可以使用 Newton-Raphson 方法进行此计算?怎么样?
【问题讨论】:
我在上次采访中被问到这个问题,并再次期待它。面试的对象是为嵌入式系统编程的固件工程师。可用于这些应用的微处理器和微控制器通常不是很强大,更简单的微处理器和微控制器不具备进行浮点计算的能力(内部没有乘法器或除法器)。
那么这个问题的可能答案是什么?定点算术与这个有什么关系(如果有的话)?
是否可以使用 Newton-Raphson 方法进行此计算?怎么样?
【问题讨论】:
ENIAC 仅使用加法和减法计算平方根。 根据前n个奇数之和为n平方的公式。
要计算m的平方根,求前n个奇数之和超过m的最小整数n。这可以通过从 m 中减去连续的奇数整数来完成,直到获得负结果。如果 n 是满足m - (1 + 3 + 5 + ... + 2n-1) < 0 的最小整数,则为(n - 1)^2 <= m < n^2。令a等于第n个奇数2n - 1,解二重不等式(n-1) <= sqrt(m) < n为
a - 1 <= 2*sqrt(m) < a + 1
或
(a - 1)/2 <= sqrt(m) < (a + 1)/2
来源: http://www4.wittenberg.edu/academics/mathcomp/bjsdir/ENIACSquareRoot.htm
但是,这实际上不适用于 m = 2,仅适用于大数。
【讨论】:
是的,您可以使用 Newton-Raphson 计算平方根。通常它是这样完成的:
设 x 为数字。我们将首先近似 1/sqrt(x),然后将其乘以 x 得到 x/sqrt(x),即 sqrt(x)。
给定 x,粗略估计 1/sqrt(x)。通常,这是通过一个小的查找表来完成的,但任何合理的估计就足够了(包括 1)。调用初始估计 e0。
根据需要重复此步骤多次:根据当前估计值 ei,创建一个新估计值 ei+1 = 1/2·e i·(3−x·ei2)。通常,所需的步数可以通过数值分析、1/sqrt(x) 初始估计的质量以及应用程序所需的精度提前确定。
最后,返回最后一个 ei·x 用于 sqrt(x) 的估计。
这个数列收敛很快,常用于计算平方根。您可以从Wikipedia page on Newton’s method 开始了解如何推导出平方根倒数的序列。另请注意,它不使用除法,这通常是一个缓慢的操作。
您将使用定点进行这些计算,因为您需要比整数提供的精度更高的精度,但浮点不可用。
本质上,面试官是想看看你是否有使用嵌入式处理器数值算法的经验。
【讨论】:
与以往的任何面试问题一样,聪明的回答是提出反问。旨在澄清和消除问题的聪明问题表明您可以思考而不是简单地喷出所接受的智慧或教条,并且还将缩小问题的范围,使您的答案更可能适用。在这种情况下,没有浮点的MCU和不使用浮点的软件实现之间可能存在区别。如果是后者,那么定点肯定是相关的,但在许多应用程序中,integer square 根可能就足够了——你可能会问这个问题,但在这种情况下, isqrt(2) == 1 似乎不太可能足够。对于前者,这种情况并不排除使用浮点数。
使用浮点时,嵌入式系统中的问题通常是缺少浮点单元 (FPU),从而导致在软件中实现的浮点运算要慢得多且确定性较差。缺少 FPU 甚至硬件整数乘法或除法并不排除使用浮点数,它只是意味着此类操作要慢得多并且需要更大的代码空间。
在大多数系统上,即使没有硬件浮点支持,标准库数学函数仍将受软件浮点支持并且可以正常使用 - 即使在 8 位系统上 - 但不要指望Mega-FLOPS 的性能。在某些情况下,性能下降以及库实现的不确定性可能会妨碍其使用,在这种情况下,有许多算法可以返回更快或更确定性的性能。
如果要求根的值很大并且整数结果足够精确,那么纯整数解将是最快的,但是对于一般情况,有许多解,其中 Newton-Raphson 是其中之一,但不太可能是最优的——它是平方根算法的冒泡排序;使用它是因为它易于教授和理解,而不是因为它的性能。
使用定点是可能的,但不是内在数据类型,代码可能会变得不那么容易编写和调试。我使用library written by Anthony Williams;它是用 C++ 编写的,并定义了一个 fixed 类; C++ 的函数和运算符重载能力意味着大多数浮点代码只需将float 或double 替换为fixed 即可移植。在 ARM 处理器上,fixed 类的执行速度大约是软件浮点的五倍。然而,Anthony 的 sqrt 算法可以改进,正如我所描述的 here,其实现基于文章 The Neglected Art of Fixed Point Arithmetic - 该文章中的代码是 C 语言,因此可能更普遍适用(其中 C++要么不可用,要么不实用——尽管这是一个不同的论点!)。
Jack Crenshaw 在他的书Math Toolkit for Real-Time Programming 中用了一整章的篇幅介绍了 sqrt() 函数,他从一个朴素的 Newton-Raphson 实现开始并逐渐对其进行改进。他还提出了一个整数解,但有趣的是不是定点的。杰克在书中包含的一些内容已经出现在他的期刊文章中;比如他对integer square-root的处理。
不管怎样,我可能会这样回答这个问题:
我会评估标准库软件的浮点性能、精度和对代码大小的影响,只有当我发现它不足以满足应用程序要求时,我才会考虑使用已建立的算法和可能的定点算法的优化解决方案.
注意我使用的术语“一种既定算法”;它有效地忽略了这样一个事实,即我可能不知道或不记得任何特定算法的名称,而我真正想说的是我不知道哪种算法是合适的,但我没有愚蠢到重新发明轮子,因为我不太可能想出比目前还没有的东西更好的东西,并且通过仔细的研究和评估,如果可行的话,我会达到预期的结果。如果受访者事先提出了这个答案并提出了一些聪明的问题,我会发现这完全可以接受。当然,面试官可能不像你那么聪明,并且可能有一个他认为是“正确”的特定答案;你可能不想在一个有这种教条反应的组织中工作。面试是一个双向的过程 - 您正在面试该组织,看看您是否愿意为您的服务带来好处。
【讨论】: