我有一个很长的"二进制字符串",就像PHPs pack函数的输出一样.
如何将此值转换为base62(0-9a-zA-Z)?内置的数学函数溢出了这么长的输入,而BCmath没有base_convert函数,或者没有特定的东西.我还需要一个匹配的"pack base62"功能.
我认为这个问题背后存在着误解.基本转换和编码/解码是不同的.的输出base64_encode(...)
是不是一个大的基于64位数字.它是一系列离散的base64值,对应于压缩函数.这就是BC Math无法工作的原因,因为BC Math关注的是单个大数字,而不是实际上代表二进制数据的小数字组的字符串.
这是一个说明差异的例子:
base64_encode(1234) = "MTIzNA==" base64_convert(1234) = "TS" //if the base64_convert function existed
base64编码将输入分成3个字节(3*8 = 24位)的组,然后将每个6位子段(2 ^ 6 = 64,因此"base64")转换为相应的base64字符(值为" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + /",其中A = 0,/ = 63).
在我们的示例中,base64_encode()
将"1234"视为包含4个字符的字符串,而不是整数(因为base64_encode()
不对整数进行操作).因此,它输出"MTIzNA ==",因为(在US-ASCII/UTF-8/ISO-8859-1中)"1234"是二进制的00110001 00110010 00110011 00110100.这被分为001100(十进制12,字符"M")010011(十进制19,字符"T")001000("I")110011("z")001101("N")00.自上一组以来如果不完整,则用0填充,值为000000("A").因为一切都是由3个输入字符组完成的,所以有2组:"123"和"4".最后一组用='填充以使其长3个字符,因此整个输出变为"MTIzNA ==".
另一方面,转换为base64需要一个整数值并将其转换为单个base64值.对于我们的示例,如果我们使用与上面相同的base64值字符串,则1234(十进制)是"TS"(base64).向后工作,从左到右:T = 19(第1列),S = 18(第0列),所以(19*64 ^ 1)+(18*64 ^ 0)= 19*64 + 18 = 1234 (十进制).相同的数量可以表示为十六进制的"4D2"(base16):(4*16 ^ 2)+(d*16 ^ 1)+(2*16 ^ 0)=(4*256)+(13*16 )+(2*1)= 1234(十进制).
与采用字符串并对其进行更改的编码不同,基本转换不会改变实际数字,只是更改其显示.十六进制(base16)"FF"是相同数目为十进制(base10)"255",这是相同数量的二进制(BASE2)"11111111".认为它像货币兑换,如果没有改变汇率:$ 1美元具有相同的价值£0.79英镑(汇率为今天的,但假装它永远不会改变).
在计算中,整数通常操作上为二进制值(因为它是容易建立1位运算单元,然后将它们堆叠在一起,以使32位/等.算术单元).要执行"255 + 255"(十进制)这样简单的操作,计算机需要先将数字转换为二进制("11111111"+"11111111"),然后在算术逻辑单元(ALU)中执行操作.
基地的几乎所有其他用途纯粹是为了方便人类(表现) - 计算机将其内部值11111111(二进制)显示为255(十进制),因为人类被训练为对十进制数进行操作.该函数base64_convert()
不作为标准PHP指令集的一部分存在,因为它对任何人都不常用:没有多少人本地读取base64数字.相比之下,二进制1和0有时对程序员有用的(我们可以使用他们喜欢的开启/关闭开关!),16进制为便于人体编辑二进制数据,因为一个完整的8位字节可以明确为00到FF表示,没有浪费太多空间.
您可能会问,"如果基本转换仅用于演示,为什么BC Math存在?" 这是一个公平的问题,也正是为什么我说"几乎"纯粹用于演示:典型的计算机仅限于32位或64位宽的数字,这通常足够大.有时您需要操作非常大的数字(例如RSA模数),这些数字不适合这些寄存器.BC Math通过充当抽象层来解决这个问题:它将大数字转换为长文本字符串.当需要进行一些操作时,BC Math会将长串的文本细分成计算机可以处理的小块.这是很多,很多比本地操作慢,但它能够处理任意大小的数字.