定点乘法算法
我正在尝试将时间戳(仅秒的小数部分)从纳秒(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是凭经验确定的,以消除截断所有低阶位的下冲,但它没有做到最好的工作。
没有找到相关结果
已邀请:
2 个回复
社攻取墟槽
基本定点乘法,使用四个16x16 - > 32个产品模拟32x32 - > 64产品。选择常数
以使用简单的二进制搜索来最小化误差。在整个有效范围内,该表达式对于+/- 0.6 NTP是好的。 比例因子中的前导
在班次中处理。编译器通常可以为这类事物生成相当不错的代码,但如果需要,通常可以使用手写汇编来简化。 如果你不需要那么多精确度,你可以摆脱
和
并得到一个好的+/- 1.15 NTP的答案:
眠缝