为什么在ruby中从秒(毫秒精度)作为浮点值转换为时间会导致ruby中不一致的精度损失?

为什么在ruby中从秒(毫秒精度)作为浮点值转换为时间会导致ruby中不一致的精度损失?,ruby,Ruby,使用Time.at函数转换表示自历元起秒数的浮点(毫秒精度),然后提取微秒值时,结果是精度损失不一致 例如,自1970年以来每年使用1月1日: ruby-e'require(“时间”);p(1..50).map{| offset | Time.at(Time.parse({1970+offset}-01-01T00:00:0.123})到{r.分子/1000.0).usec}' [122999, 123000, 122999, 122999, 122999, 122999, 122999, 12

使用
Time.at
函数转换表示自历元起秒数的浮点(毫秒精度),然后提取微秒值时,结果是精度损失不一致

例如,自1970年以来每年使用1月1日:

ruby-e'require(“时间”);p(1..50).map{| offset | Time.at(Time.parse({1970+offset}-01-01T00:00:0.123})到{r.分子/1000.0).usec}'
[122999, 123000, 122999, 122999, 122999, 122999, 122999, 122999, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 123000, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999, 122999]
根据-中的讨论,我预计亚秒值始终会有精度损失(即始终为
122999
)。

TL;博士(来自)

请注意,IEEE 754 double不够精确,无法表示自新纪元以来的精确纳秒数


关于您的期望:

我希望亚秒值始终会有精度损失(即始终为122999)

损失≠ 较少的“精度损失”并不意味着结果总是小于实际值。例如,由于精度损失,添加
0.1
0.2
会导致值略高于
0.3

0.1 + 0.2 #=> 0.30000000000000004
回到你的时间价值观。让我们先看看前两年,1971年和1972年:

Time.parse('1971-01-01T00:00:0.123').to_f #=> 31532400.123
Time.parse('1972-01-01T00:00:0.123').to_f #=> 63068400.123

Time.at(31532400.123).usec #=> 122999
Time.at(63068400.123).usec #=> 123000
这是因为浮点不准确。浮点数的实际值为:

31532400.1229999996721744537353515625
63068400.123000003397464752197265625
#        ^^^^^^
#         usec
调用nsec表明上述两项事实上都不准确:(一项略低于,另一项略高于)

要获得精确的值,必须提供精确的参数:

Time.at(31532400123.quo(1000)).usec #=> 12300

# or

Time.at(31532400, 123000).usec #=> 12300
Time.at(31532400123.quo(1000)).usec #=> 12300

# or

Time.at(31532400, 123000).usec #=> 12300