如何安全将64位浮点型UNIX时间戳转换为纳秒且避免溢出?
将带小数的64位浮点型UNIX时间戳转换为纳秒的安全性疑问
我持有一个带小数部分的64位浮点型UNIX时间戳(例如1687976937.597064),需要将其转换为纳秒。此前误以为直接乘以10亿会导致64位浮点数溢出,该结论已修正。
各类数值的存储限制
- 目标结果:
1_687_976_937_597_064_000(原时间戳乘以10亿后的整数) - 64位有符号整数最大值:
9_223_372_036_854_775_807 - 64位浮点数的精确整数上限为
9_007_199_254_740_992.0,此前误以为该级别无法存储小数,实际是浮点数舍入误差,详见文末说明 - 结论:64位有符号整数可容纳目标结果,但64位浮点数无法精确存储,会出现溢出/舍入问题
我的转换思路
- 提取时间戳的整数部分转为整数,乘以10亿
- 提取小数部分(格式为
0.XXXXXX),乘以10亿。由于小数部分整数位为0,结果不会超过1_999_999_999.XXXXX,乘法操作安全 - 将小数部分的乘法结果截断为整数
- 将两个整数相加得到最终纳秒值
这个方法看似可行,但流程比较粗糙,是否存在安全隐患?
Python交互式环境测试过程
>>> num = 1687976937.597064 >>> whole = int(num) >>> whole 1687976937 >>> decimals = num - whole >>> decimals 0.5970640182495117 >>> (whole * 1_000_000_000) 1687976937000000000 >>> (decimals * 1_000_000_000) 597064018.2495117 >>> int(decimals * 1_000_000_000) 597064018 >>> (whole * 1_000_000_000) + int(decimals * 1_000_000_000) 1687976937597064018 >>> type((whole * 1_000_000_000) + int(decimals * 1_000_000_000)) <class 'int'>
结果对比
- 上述算法得到的结果:
1_687_976_937_597_064_018,存在轻微浮点数舍入误差,我可以接受 - 科学准确结果(Wolfram Alpha计算):
1_687_976_937_597_064_000
该方法测试看似成功,但有没有失效风险?未确认安全性前,我不敢将其投入生产环境。
关于64位浮点数限制的补充测试
>>> 9_007_199_254_740_993.0 9007199254740992.0
此前对64位浮点数“限制”的理解有误,这其实是浮点数的舍入误差导致的结果。
内容的提问来源于stack exchange,提问作者Mitch McMabers
相关产品推荐
相关产品推荐

