【问题标题】:Understanding bits and time in milliseconds以毫秒为单位了解位和时间
【发布时间】:2021-05-12 14:19:40
【问题描述】:

我正在阅读 this 页面,其中说 41 位用于使用自定义纪元表示 41 年。

我无法理解以毫秒、位和年为单位的时间之间的关系。有人可以帮忙吗?

例如。在 Java 中,System.currentTimeMillis() 返回一个long,即64 bits。这是否意味着如果我必须每毫秒生成 1 个,它可以代表 64 年的独特价值?

在上述情况下,41 年后会发生什么?如果他们保持相同的方法,他们是否必须增加用于指定的位?

【问题讨论】:

  • 旁注:你的意思可能是System.currentTimeMillis()?
  • 没有关系,那篇博文的情况纯属巧合。这只是数学。 X 位可以表示从 0 到某个数字的范围,如果您说该数字是毫秒,那么只需进行数学运算,看看它是多少年。
  • 我投票结束这个问题,因为它只是一个数学问题。
  • 谢谢!是的,这就是让我彻底失望的原因。

标签: java epoch milliseconds


【解决方案1】:

例如。在 Java 中,System.timeinmillis() 返回一个 long,即 64 位。这是否意味着如果我必须每毫秒生成 1 个,它可以代表 64 年的独特价值?

不,远不止这些。不要忘记,您在存储中添加的每一位,都会存储两倍的值。

2^64 是 18,446,744,073,709,551,616。这就是 64 位整数数据类型中可以保存的不同值的数量。

所以在毫秒精度下,就是:

  • 18,446,744,073,709,551,616 毫秒
  • 18,446,744,073,709,551 秒
  • 307,445,734,561,825 分钟
  • 5,124,095,576,030 小时
  • 213,503,982,334 天
  • 584,542,046 年

也称为“可能比您需要的范围更大”:)

【讨论】:

  • @WJS:括号中的位是上次尝试遗留下来的。现已删除:)
  • 谢谢!这就是我想知道的,为什么他们将 41 位映射到 41 年,而 41 位可以代表很多年。 @rtwitserloot 的回答澄清了这一点!
【解决方案2】:

这是一个奇怪的巧合和奇怪的写作方式。 41 位实际上是 69 岁,而不是 41 岁。本文档的作者搞砸了或过于简单化了,但请注意,69 非常接近 41,纯属巧合。

让我们深入研究一下我们所知道的:

他们明确指出这是某种“毫秒”值。我们也知道它是 41 位,其余的,嗯,我们将不得不猜测。

让我们处理我们所知道的东西:41 位和“毫秒”。

41 位就像 41 个独立的电灯开关。想象一下下面的游戏:

你可以进入一个房间。它里面有1个电灯开关,没有其他值得注意的。除了电灯开关,您不能留下任何东西、在墙上划伤或以其他方式与这个房间互动。然后,你得走了。那我过一段时间再进去。

我们可以交流多少信息?

使用一个电灯开关,只需 1 位信息:您可以让灯开或关,这就是我所知道的全部。如果您需要与我交流的只是您观察到的硬币翻转的结果而我没有,那么我们只需要 1 位。我们事先做了一个安排:灯关向下表示硬币落反,灯亮表示正面落下。瞧,我们现在可以交流 1 次抛硬币。

假设有 2 个电灯开关。您现在可以交流 4 种不同的事物。假设有人从一副牌中抽出一张牌,你看到了,而我没有:如果我们安排一个“代码”,你可以将这套牌传达给我。

把'light switch off'当作0,'light switch on'当作1,那么我们可以预先安排这段代码:

00 - hearts
01 - clubs
10 - spades
11 - diamonds

所以,如果我进入房间,我看到左边的灯开关是关闭的,而右边的开关是打开的,我可以说:你画了一个俱乐部!那就对了。

您添加的每个电灯开关都会使您可以交流的状态数量翻倍。所以,1 个灯开关有利于区分 2 件事(例如硬币翻转),2 个开关可以做 4 个事情,3 个开关可以做 8 个,4 个开关可以做 16 个等等。

这里有 41 个电灯开关。这有助于区分 2^41 或 2,199,023,255,552 不同的唯一值。通过简单的数学运算。

我们也知道这是在“毫秒”之间进行区分。让我们将其解读为:该机制能够以 1 毫秒的粒度存储时间。换句话说,只要这 2 个时间点至少相差 1 毫秒,它就可以分辨出任意 2 个时间点。

让我们以毫秒为单位:

  • 除以 1000 秒。
  • 除以 60 分钟。
  • 除以 60 小时。
  • 除以 24 天。
  • 除以 365.25 年。

所以让我们这样做吧。 2,199,023,255,552/1000/60/60/24/365.25 = 69.682842027。

换句话说,有了 41 个电灯开关,您可以以毫秒的粒度及时与我交流,只要我们提前安排好我们知道我们只在特定的时间范围内交流,并且这个范围不能超过 69 年半。

进行这种安排的最简单方法是将某个时间点定为“纪元” - 0 值。

例如,我们可以做这样的预先安排:

  • 让我们规定 UTC 时区,新年是 1999 年变成 2000 年,那个瞬间,我们称之为 0。然后这个数字代表毫秒数之后。

因此,数字 60000 编码的时刻(在 UTC 时区)是 2000-01-01 00:01:00(UTC 时区 2000 年午夜后 1 分钟)。

换句话说,我进入房间,我注意到所有的电灯开关都关闭了,除了右边的第二个和第三个:0000...00110。我们事先安排了这是通常的二进制计数机制,所以是 6。因此,我知道您试图告诉我这张照片是 2000 年 UTC 时区午夜后 6 秒拍摄的。

我们的 41 位让我们到达 2069 年 7 月 1 日左右(2069 年 7 月),然后我们完全用完了位。如果你只是盲目地继续计数,那么计算机会绕圈子,所以你又会得到数字 0,而我们会错误地将其解读为:Juuust at午夜,2000 年。

换句话说,是69岁,41岁就是完全的马粪。我不知道他们为什么写 41。但是,41 至少接近 69,所以可能是过于简单化了。

当他们遇到 2041 或在他们自己的文档中修复错误 2069 时会发生什么?好吧,一个简单的解决方案,例如再买 10 年就是下令将 0 读作 2069 年 8 月,而不是 2000 年,这没关系,因为 instagram 还没有出现。但这只会让你多活几年。

然后,要么真的很老的 instagram 帖子突然看起来像是来自 2080 年(通过向上重新定义 69 位窗口,任何不在窗口中的时间戳看起来都像,因此是完全错误的),或者他们改变了他们的 ID 系统,例如添加另外几位。他们添加的每一位都加倍窗口大小。即使是 1 位也足够再过 69 年。

【讨论】:

  • 知道了!!感谢您写出如此详细的答案,非常感谢!顺便说一句,对于0000...00110,您的意思是照片是在午夜之后拍摄的 6 milliseconds,而不是您所写的 seconds
【解决方案3】:

没有。 41 位的 41 年并不意味着 64 位将产生 64 年。起初:这不是真的。 2^41/1000/60/60/24/365.24 评估为近 70 年,而不是 41 年。第二:如果 41 位是 41 年,那么 42 位将是 82 年,而 43 位将是 164 年。明白了吗?每个新位都会使结果翻倍。因此,64 位足以使用数百万年。

【讨论】:

    【解决方案4】:

    时间的标准纪元是 1970 年 1 月 1 日。

    long v = LocalDate.now().getLong(ChronoField.EPOCH_DAY);
    long millis = v*24*3600*1_000L; // total possible milliseconds
    System.out.println(Long.toBinaryString(millis).length()); // length = 41
    

    因此需要 41 位 long 来表示自 Epoch 以来的毫秒数。剩下 23 位,这将是相当长的几年(严重轻描淡写)。

    【讨论】:

      猜你喜欢
      • 2014-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多