为了回答这个问题,我们需要先追溯到人们最常用的十进制计数上。计算机科学是对“2”特别敏感的一个学科。而人们自然运算时是对“10”敏感的,人们一般使用十进制作进行自然运算,因此对“10”的倍数特别进行了定义。比如10的2次方是百,10的3次方是千,10的4次方是万……“个十百千万”是连幼儿园小朋友都知道的东西。人们由此定义了:
100 hundred 1,000 thousand 1,000,000 million 1,000,000,000 billion 1,000,000,000,000 trillion 1,000,000,000,000,000 quadrillion ... ...
我们暂时忽略“个十百”,可以看到“千”是一个特别的存在,以“千”为基础(千的乘方)定义了后面的单位(都是3个零一定义)。
于是数学上为了方便,给这些单位定义了前缀符号,叫 Metric prefix(或 SI prefixes),如(符号"^"表示乘方):
10^1 = 1deca = 1da 10^2 = 1hecto = 1h 10^3 = 1kilo = 1k
其中kilo就表示1000这个量级,简写为k。从这个量级开始,后面的定义都以“千”为基数继续定义出了后面的单位:
10^3 = 1000^1 = 1kilo = 1k 10^6 = 1000^2 = 1mega = 1M 10^9 = 1000^3 = 1giga = 1G 10^12 = 1000^4 = 1tera = 1T 10^15 = 1000^5 = 1peta = 1P ... ...
这些是人们基于常用的10进制做的定义。
说完十进制的一些事情后,我们再来看二进制。因为电子计算机普遍采用二进制,所以人们像对待10进制那样对待2进制的单位。为什么将1024这个定义为二进制的“千”,因为它是2的乘方倍数中最接近十进制常用的“1000”的存在。人们将10^3定义为千,而2^9=512,2^11=2048,只有2^10最接近1000,而且正好阶乘还是人们喜闻乐见的“10”。所以2^10=1024就被视为二进制中的“千”。
但是毕竟1024和1000是不一样的,由2的乘方所定义出的数字也和10的乘方不一样,比如:
2^10 = 1024 2^20 = 1048576 2^30 = 1073741824
所以不能将上面提到的kilo, mega, giga直接用于此处,因为这些是基于十进制定义出来的。所以人们“模仿”十进制时用到的定义,又做了用于二进制的定义,叫 Binary prefix:
2^10 = 1024^1 = 1kibi = 1Ki 2^20 = 1024^2 = 1mebi = 1Mi 2^30 = 1024^3 = 1gibi = 1Gi 2^40 = 1024^4 = 1tebi = 1Ti 2^50 = 1024^5 = 1Pebi = 1Pi ... ...
可以看到用于二进制的单位的结尾都带一个“i”,所以严格来说,当你说"1KB"的时候,实际是"1000 Bytes"的意思,而如果要表达"1024 Bytes",应该写作"1KiB"。因为"1K"严格来说是"1000"的意思,而"1Ki"才是"1024"。
举个例子,比如我买了一个U盘(我确实买了一个),厂商标的是128GB,所以如果严格来说,我应该期望看到拥有:
128*1,000,000,000 Bytes = 128,000,000,000 Bytes
这么大的一个U盘。但是我实际看到的是:
# fdisk -l /dev/sda Disk /dev/sda: 114.56 GiB, 123010547712 bytes, 240254976 sectors Disk model: Ultra Luxe Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xab01f680 Device Boot Start End Sectors Size Id Type /dev/sda1 1 240254975 240254975 114.6G 7 HPFS/NTFS/exFAT
也就是说实际上厂商只给了我240254976个sectors(每个sector是512字节大小),也就是给了我123,010,547,712 Bytes大小的空间。这根本就只有大概123GB,或者说大概114.6 GiB。
最后我们说一下现实中常见的混淆使用。虽然我们上面说从某些标准的严格定义来说,K和Ki,M和Mi,G和Gi等是不同的概念,代表的大小也不同。但是在人们实际的使用中,常常是混淆使用的。
就比如我上面U盘的那个例子,fdisk的输出信息中第一行使用的是114.56 GiB,但是最后一行就将Gi写作了"G"。
所以现实中当你看到k/K, m/M, g/G等单位时,一定要根据上下文来判断它代表的到底是十进制的还是二进制的情况。从我个人实际的各种使用经历来看,程序员们对这些单位的使用并不那么“严格”。这一点在一般情况下(不是严格的发表论文的场景),也没必要特别计较。