轨道
/
Java
Java
/
练习
/
星际传输
星际传输

星际传输

中等

简介

地球与邻近星系之间,每毫秒都有数以万亿计的消息飞驰而过。 但要在如此遥远的距离上传输,并不容易。 恼人的太阳耀斑、时间扭曲、杂散的力场,甚至一只太空蝴蝶扇动翅膀,都可能让某个比特在传输过程中随机发生改变。

现在想象一下后果:

  • 让星际股票市场崩盘:“buy low”变成了“sell now”。
  • 与 Kepler Whirl 星系失去联系:“save new worm hole”变成了“cave new worm hole”。
  • 或者把牛仔表情 🤠 换成小丑表情 🤡,让整个宇宙陷入存在主义式的恐惧。

检测出损坏的消息不只是重要,而是至关重要。 接收方_必须_在灾难降临之前知道哪里出了问题。

但怎么做到呢? 宇宙各地的科学家和工程师已经和这个问题斗争了亿万年。 整个宇宙的人工智能超级集群都在不停运算这些数据。 直到有一天,一个传说重新浮出水面:一种古老而强大的方法,在调试论坛上被人低声提起,被那些见识过太多的工程师们反复念叨……

奇偶校验位!

一种如此简单、如此强大的方法,也许正好能拯救星际通信。

说明

你的任务是帮助实现

  • 发送器,负责计算传输序列;
  • 接收器,负责解码。

奇偶校验位是一种检测传输错误的简单方法。 发送器和接收器每次只能发送和接收恰好八位(包括奇偶校验位)。 奇偶校验位的取值使得每次传输中 1 的个数为偶数,而且奇偶校验位始终是从右边数起的第一位。 因此,如果接收器收到 11000001、01110101 或 01000000(即一次传输中 1 的个数为奇数),它就知道出错了。

不过,消息很少这么短;当消息较长时,就需要按序列来传输。

例如,考虑消息 11000000 00000001 11000000 11011110(十六进制为 C0 01 C0 DE)。

由于每次传输恰好包含八位,因此其中最多只能有七位数据和一位奇偶校验位。 所以每七位数据之后都必须插入一个奇偶校验位:

11000000 00000001 11000000 11011110
      ↑       ↑       ↑       ↑          (7th bits)

这条消息的传输序列如下:

1100000_ 0000000_ 0111000_ 0001101_ 1110
       ↑        ↑        ↑        ↑      (parity bits)

序列中第一次传输的数据(1100000)有两个 1(偶数个),因此奇偶校验位为 0。 第一次传输变成 11000000(十六进制为 C0)。

下一次传输的数据(0000000)中 1 的个数为零(同样是偶数个),因此奇偶校验位仍然是 0。 第二次传输由此变成 00000000(十六进制为 00)。

接下来两次传输的数据(0111000 和 0001101)有三个 1。 它们的奇偶校验位被设为 1,使整个传输中 1 的个数为偶数。 它们的传输形式是 01110001 和 00011011(十六进制为 71 和 1B)。

最后一次传输(1110)只有四位数据。 由于每次传输恰好是八位,而奇偶校验位在最右边,因此要先补三个 0,再加上奇偶校验位,凑足八位。 现在它看起来是这样(其中 _ 代表奇偶校验位):

1110 000_
     ↑↑↑   (added 0 bits)

1 的个数又是奇数,所以奇偶校验位为 1。 序列中最后一次传输变成 11100001(十六进制为 E1)。

这条消息的完整传输序列是 11000000 00000000 01110001 00011011 11100001(十六进制为 C0 00 71 1B E1)。

实现

虽然我们处理的是字节数据,但输入和输出都是List<Integer>(而不是byte[]),这样就无需为 128 到 255 的字节做强制类型转换或负值转换。


来源

Kah Goh链接会在新窗口或新标签页中打开
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Java Exercism

准备好开始 星际传输 了吗?

注册 Exercism,借助 26 个概念158 个练习 和真人导师指导,学习并掌握 Java,全部免费。