您的计算机如何处理整数
这是与了解您的计算机及其软件相关的一系列博客文章中的第一篇博客文章。 目的是进一步了解Swift的内部,性能和性能。 我们将介绍计算机(数学)的基础知识,以及结构,数组和快速优化。
这篇文章将介绍位,字节,整数和数学。
位
在计算中,一切都是二进制的。 迅速地, 0b
前缀表示字节文字的开始。 然后,所有数字( 0
或1
)将字节中的位表示为小端。
0b00000000
该字节为0
,因为所有位均为0。
字节序
这些位按从大到小(小端)或从小到大(大端)的顺序排列。 Endian,即列表中的最后一位,即列表中最小或最大的数字。
0b10100000
小尾数中的以下数字是128 + 0 + 32 + 0 + 0 + 0 + 0 + 0
,因此为150
但是,在big endian中,这是1 + 0 + 4 + 0 + 0 + 0 + 0 + 0
,因此是5
。
最低位代表1
,每步乘以2
。
大端:
1,2,4,8,16,32,64,128
或小端:
128、64、32、16、8、4、2、1
文字
通常,在写整数时,是在写十进制数。
0b00001010
是代表10
的二进制数。 在编写人工代码时,这不是特别有用。 但是有时候,在处理非常底层的代码时,有必要理解和/或编写。
让十= 10
让alsoTen = 0b00001010
二进制是一种系统,其中每个2的幂都使用一个额外的数字。 我们称此为“基数2”。 同样,我们使用的小数点是“以10为底”。
零是0
,一是1
。 但是两个是10
。
在十进制(使用10的幂的系统)中,其工作方式相同。
Zewo是0
是1
。 但是2是2
,因为它低于10。 这继续进行到九( 9
)。 但是,当我们达到10时,我们将数字设置为0
并添加1
。
因此,十进制的10
是(10¹) + 0)
,或者10
(10¹) + 0)
1的幂加0。
当我们以小数达到100
时,将变为(10²) + (0¹) + 0
。 看到趋势了吗?
让我们将其应用于二进制。
0b10 ==(2¹)+ 0
由于2¹ == 2
这意味着0b10
是十进制的2
,这是正确的。 让我们再做一个。
0b101 ==(2²)+(0¹)+ 1
这将使二进制数为101
,十进制数为5
(五),这也是正确的。
十六进制
这就是十六进制起作用的地方。 写大的二进制数虽然很有效,但是却很快变得不可读。 但是,写十进制与二进制文件不能很好地配合。 用十进制表示二进制数会造成混淆。 因此,十六进制(基数为16)填补了这一空白。
0b010100000
(或十进制的80
)很难读取和计算。 因此,我们创建了第三个可以使用的系统,该系统是十六进制或使用16的幂。
这通过添加数字(十,十一,十二,十三,十三,十四和十五)来利用现有的十进制系统。 或a
, b
, c
, d
和f
依次排列。
十六进制(有时缩写为“十六进制”)的优势在于,它在保持可读性的同时,可以代表比二进制甚至十进制更好的大量数字。 除了可以读取大量数字外,它不会失去十进制所具有的与二进制的兼容性。 稍后我们将讨论移位和其他数学运算时,将对此进行更多介绍。
十六进制的0b01010000
是0xa0
。 或(因为a
代表10
) (10¹) + 0
。
签名位
整数之间又有一个区别。 上面的整数是一个8位无符号整数。
这些整数不能为负。 因此,一个8位无符号整数可以表示的最大数目为255
。
是128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
或0b11111111
。
最小的可表示数字是0
或0b00000000
。
签名位是单个位,用于定义数字是否为负数,而不是最高位。
无符号的0b10000001
是128 + 1
或129
。
带符号的相同数字是-1
,因为128
代表-
,而下一个数字是1
。
加成
二进制数学非常简单。 在这里,我们将使用4位无符号集,最大数量为(1 + 2 + 4 + 8)
或15
。
0b0001 + 0b0010 == 0b0011
以上是1 + 2 == 3
(十进制)。 我们的计算方式与十进制相同。
C = A + B
,如果C
大于我们正在研究的基数的阶数,则C
的结果为1
,高1个数量级。 其余的保持在这个数量级。
4 + 8 == 12
由于4 + 8
大于我们正在处理的基数(基数10),因此我们创建一个10
( 10^(current_magnitude + 1)
),然后将余数乘以2 * (10 ^ current_magnitude)
。 由于大小为0
,因此变为12
。
如果我们将其应用到更高的数量级。
40 + 80 == 120
40
在一个数量级为4
,而80
在一个数量级为8
。
当4 + 8
大于9
(一个数量级的最大数)时,这将成为一个新的数量级,余数为2
。
//基数(10)^(数量级+ 1)
让newOrder =(10 ^(1 + 1))
// 2 ^数量级
让newRemainder =(20 ^ 1)
最后但并非最不重要的一点是,您从较低的数量级开始工作。 您记下其余部分,然后将新的数量级(如果有)添加到下一个总和。
119 + 873
3 + 9是(2余数,下一个幅值的1)
7 +1 + 1是(9余数,下一个幅值的0)
1 + 8是(9,0表示下一个幅度)
从高到低的顺序变为“ 992”,这是正确的。
相同的二进制工作原理,只是数量级不同。
0b0001 + 0b0001 == 0b0010
0b0011 + 0b0010 == 0b0101
整数溢出
操作员无处不在。 它们用于加,减,乘和除。 它们被用作合并数组的语法糖,并且列表不断。
具体地说,前三个与其他语言不同。
用任何语言加上2个数字将得出预期的总和。
1 + 2 == 3
假设您有一个存储0b11111111
的无符号整数。 您要添加0b00000001
。
结果:
0b11111111 + 0b00000001 == 0b100000000
结果数字有9位。 如果您使用的是普通整数,那很好。 但是在这种情况下,我们使用的是UInt8
或Unsigned 8位整数。 如您所见,8位整数中不能容纳9位,因此剩余(最高)位将丢失。
Swift的+
运算符对此具有保护作用。 如果检测到+
运算符产生的数字大于该数字的容量,它将使您的应用程序崩溃。
如果您100%确定您的电话号码永远不会溢出,则可以使用&+
运算符禁用此检查。
让三个= 1&+ 2
让alsoThree = 0b00000010 + 0b00000001
通过取消检查,您不仅可以禁用安全机制,还可以提高性能。 但是请谨慎使用。 在任何地方使用此运算符都可能会引入严重的错误,并使您的应用程序更容易受到黑客攻击。 但是,在某些情况下,可以保证获得性能是值得的。