我正在尝试将时间戳(仅秒的小数部分)从纳秒(以 10^-9 秒为单位)重新调整为 NTP 时间戳的下半部分(以 2^-32 秒为单位)。实际上,这意味着乘以 4.2949673。但是我需要在没有浮点数学的情况下进行,并且不使用大于 32 位的整数(事实上,我实际上是为 8 位微控制器编写的,所以即使是 32 位数学也很昂贵,尤其是除法)。
我提出了一些运行良好的算法,但我在数值方法方面没有任何真正的基础,所以我很感激任何关于如何改进它们的建议,或者任何其他更准确的算法和/ 或更快。
算法 1
uint32_t intts = (ns >> 16) * 281474 + (ns << 16) / 15259 + ns / 67078;
选择前两个常数是为了稍微低于而不是超过正确的数字,并且根据经验确定最终因子 67078 来纠正这一点。在正确值的 +/- 4 NTP 单位内产生结果,即 +/- 1 ns - 可接受,但残差随ns
. 我想我可以添加另一个术语。
算法 2
uint32_t ns2 = (2 * ns) + 1;
uint32_t intts = (ns2 << 1)
+ (ns2 >> 3) + (ns2 >> 6) + (ns2 >> 8) + (ns2 >> 9) + (ns2 >> 10)
+ (ns2 >> 16) + (ns2 >> 18) + (ns2 >> 19) + (ns2 >> 20) + (ns2 >> 21)
+ (ns2 >> 22) + (ns2 >> 24) + (ns2 >> 30) + 3;
基于 4.2949673 的二进制展开(实际上是基于 2.14748365 的二进制展开,因为我是先加倍加一来完成四舍五入的)。可能比算法 1 更快(我还没有完成基准测试)。+3 是根据经验确定的,以抵消截断所有这些低位的下冲,但它并没有做最好的工作。