UInt128 与它所包含的 2 个 UInt64 有何关系?

How does a UInt128, relate to the 2 UInt64s it's comprised of?

如果我有以下结构:

public struct UInt128 {
    internal var value: (upperBits: UInt64, lowerBits: UInt64)
}

想象一个初始化程序,它创建一个适合 UInt128 的随机数,并且该数字足够大,以至于它超过 UInt64

之一的值

高位和低位之和是UInt128的总和还是另一种方式管理的内存?

为了处理小数,如果每个 UInt64 的容量是 20,如果 UInt128 的值是 24,高位值是 20 而低位是位值是 4?

我认为对于这个问题,您将得到的任何答案都过于简单化了,但这是我的看法:

低位代表数字0到2^64-1,高位代表数字2^64到2^128-1

如果您有两个 64 位数字并想将它们相加,您可以将较高的位向左移动 64 位。

这对您的理解有帮助吗?

假设你被要求制作一个代表 4 位数字的 struct,但你只能存储 2 位数字。因此,您有一个 upperHalf 表示前 2 位数字和一个 lowerHalf 表示后 2 位数字。

let upperHalf = 12
let lowerHalf = 34

现在,您想将它们组合起来组成完整的 4 位数 1234

你是怎么做到的?你加了吗?

12 + 34 = 46

不,因为 12 不仅仅代表 12。真是1200.

1200 + 34 = 1234

所以为了组合它们,你将 upperHalf 乘以 100 得到 使 space 为较低的数字,然后添加lowerHalf.

let upperHalf = 12
let lowerHalf = 34
let value = upperHalf * 100 + lowerHalf
print(value)  // 1234

那么,什么是100?它表示将一个以 10 为基数的数字左移 2 位。对于每个班次,您乘以 10。所以 2 班次是 10 * 10100.

现在您的任务是使用两个 UInt8 数字来表示一个 UInt16 数字。

let upperBits = 2
let lowerBits = 1

现在您想将它们组合起来形成 UInt16 值。与之前的情况一样,您不能只添加它们。您需要将 upperBits 向左移动 8 位,以便为 lowerBits 腾出空间。但是现在您使用的是二进制(基数为 2),因此每次移位都是通过乘以 2.

来完成的

因此,将两个 UInt8 值的 upperBitslowerBits 合并为

let value = (upperBits * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2) + lowerBits

等同于:

let value = (upperBits * 256) + lowerBits

也可以写成:

let value = (upperBits << 8) + lowerBits

<< 8表示将位左移8次。

所以如果 upperBits2 并且 lowerBits1 那么

let value = (2 * 256) + 1  // value = 513

将这个类比扩展为使用两个 UInt64 数字来表示一个 UInt128,您需要在添加 lowerBits 之前将 upperBits 向左移动 64 位。每个班次都等同于乘以 2,因此您必须先将 upperBits 乘以 2 ^ 64(或 18446744073709551616)以在添加 lowerBits 之前腾出空间:

概念上:

let value: UInt128 = (upperBits << 64) + lowerBits 

与以下相同:

let value: UInt128 = (upperBits * 18446744073709551616) + lowerBits

考虑两个 UInt8 内存位置,其中最重要的值为 00000001,最不重要的值为 00000010,它们以正确的顺序加入 UInt16 为 0000000100000010,即 258。最左边的 8 位代表 256 和最右边的 2,256 + 2 = 258。或者只看 16 位 UInt16,第一个(左)1 代表 256,最后一个(右)1 代表 2.