最近开始学习研究使用Platform IO在Arduino等SoC开发版上实现特定的算法功能,为后续的工作做铺垫。原本是在调研数学运算这一块,发现Arduino开源框架没有log等内建的指数运算实现。本着研究一下看看,结果发现跑偏了研究到了sin,cos等这些三角函数实现去了(当然,我最大的希望还是能找到一个比较成熟完备的第三方数学库支持)。然后发现了一个“惊天”大秘密!
大家认为上述数学公式的答案是多少,通常毫无疑问是0,对吧。那么下面的c/c++实现的答案又该是多少呢?
答案是不确定。有可能是1.22465e-16, 也有可能是其他,和浮点数数学运算单元的精度有关,也和sin具体实现的算法有关。
过程是艰辛的,收获是满满的。
起始第一步就遇到了困难,没有找到libc/libcpp的标准库源码。本以为GCC编译器源码中会附带,但是没有发现。但是不幸中的万幸,我一不小心找到了对应的go语言的sin实现,然后在附带的链接中找到了Cephes Math Library。感谢Stephen L. Moshier!
阅读源码相对来说还算容易,Cephes Math Library中sin函数的实现并不很复杂。但是在理解其中部分源码实现的意图还是不容易的。当然整体原理比较简单,就是通过泰勒多项式展开计算获取sin函数的高精度近似值。这就是为什么sin(M_PI) != 0的根本原因。Stephen L. Moshier在保证sin计算精度上我可以看出他做了非常多的努力,但是貌似都没有获得应有的收获。中间的很多做法一直困扰了我,所以我通过自己实现了一个简单的版本来揣测作者的意图,最终豁然开朗,虽然并不完全认同作者的做法。
还是回到正题,让我们进入Stephen L. Moshier实现sin的过程。
首先,Stephen L. Moshier对传入sin函数的计算参数做了一些有效性验证,比如非数字,无穷数等等。
<