当前位置: 首页 > Web前端 > JavaScript

JavaScript二进制、十六进制

时间:2023-03-27 14:13:51 JavaScript

JavaScript内部默认情况下,二进制、十六进制、八进制字面量值会自动转换为十进制进行计算。0x22//340b111//70o33//270x22+0b111//410o33+12//39(0x33).toString()//51(0x33).valueOf()//51除了十进制是Javascript的默认数字基数,其他三个基本方法很少用到,主要是在处理底层数据,字节编码或者位操作的时候遇到。十六进制转换本文将主要讨论十六进制转换中的问题。JavaScript提供了在十进制和其他基数之间进行转换的本机函数。其中,其他基数转十进制的方式有3种:parseInt()、Number()、+(一元运算符)。这三种方法都只能转换整数。要从十进制转换为其他基数,您可以使用Number.prototype.toString()。支持小数。parseInt(str,radix)第一个参数是要解析的字符串;其他基地没有前缀。第二个参数是一个基数,表示在转换过程中使用什么基系统来理解字符串。默认值为10,表示转换为十进制。如果第二个参数不是数字,它会自动转换为数字。如果不能转换为数字,该参数将被忽略;如果是数字,则必须是2-36的整数。如果超出这个范围,则返回NaN。parseInt('1111',2)//15parseInt('1234',8)//668parseInt('18af',16)//6319parseInt('1111')//1111如果没有传入第二个参数,parseInt将Strings默认以十进制解析;但是,如果字符串以0x开头,则将其视为十六进制数。而其他base的字符串,0o21(八进制),0b11(二进制)不会自动与base的base进行转换,而是得到0。因此,在使用parseInt进行二进制转换时,为了保证正确性和稳定性运行结果,第二个参数不能省略。parseInt('0x21')//33parseInt('0o21')//0parseInt('0b11')//0parseInt('111','add')//111parseInt('111','787')//NaN如果如果待解析的字符串中有当前base无效的字符,则有效字符从最高位开始转换,没有有效字符则返回NaN。parseInt('88kk',16)//136,===0x88parseInt('kk',16)//NaNNumber()可以将字符串转为数字,支持其他基数的字符串,默认转为十进制数。如果字符串中存在无效的基本字符,则返回NaN。请记住,您需要使用基本前缀0b、0o、0x。Number('0b11100')//28Number('0o33')//27Number('0x33')//51Number('0x88kk')//NaN+(一元运算符)和Number()一样,可以转换字符串toNumbers,支持其他基数的字符串,默认转为十进制数。如果字符串中存在无效的基本字符,则返回NaN。还需要一个基本前缀。+'0b11100'//28+'0o33'//27+'0x33'//51+'0x88kk'//NaN可以看出,它和Number()基本一样,本质上都是一对数A转换过程。Number.prototype.toString(radix)支持传入一个基数,用于将数字转换成基数对应的字符串,支持转换小数。如果不指定默认值为10,radix参数的取值范围为2-36,超出范围会报错:RangeError。15..toString(2)//1111585..toString(8)//11114369..toString(16)//1111(11.25).toString(2)//1011.01除了这些原生函数,自定义转换也是可以自己实现基数之间的转换函数。根据相应的规则,可以实现一些十进制、二进制和十六进制之间的转换方法。十进制和十六进制的转换下面的代码是整数在十进制和十六进制之间的转换,转换是按基本规则进行的。十六进制是描述数字0-9、a-f的一种方式,其中0-9取其自身的值,a-f取10-15的值。字母不区分大小写。functionint2Hex(num=0){if(num===0){return'0'}constHEXS='0123456789abcdef'lethexwhile(num){hex=HEXS.charAt(num%16)+hexnum=Math.floor(num/16)}returnhex}functionhex2Int(hex=''){if(typeofhex!=='string'||hex===''){returnNaN}consthexs=[...hex.toLowerCase()]letresInt=0for(leti=0;i0){decimalVal=decimalVal*2if(decimalVal>=1){decimals.push('1')if(decimalVal>1){decimalVal=decimalVal-1}}else{小数。push('0')}count--}}constresDecimal=小数。join('')returnresInteger+(resDecimal?('.'+resDecimal):'')}小数转二进制时会出现死循环问题。上面的代码截取了前49个值。所以,这里就出现了一个问题,就是常见的数字精度问题:0.1+0.2!=0.3。0.1+0.2!=0.3只看0.1到二进制:0.1×2=0.20.2×2=0.40.4×2=0.80.8×2=1.60.6×2=1.20.2×2=0.4//循环开始0.4×2=0.80.8×2=1.60.6×2=1.2...无限循环0.2转二进制:0.2×2=0.40.4×2=0.80.8×2=1.60.6×2=1.20.2×2=0.4//循环开始0.4×2=0.80.8×2=1.60.6×2=1.2...无限循环因为得不到1,可以求有限小数,0.1转为无限二进制分数0.00011001100...,0.2转换为0.001100110011...。由于无限循环,精度将不可避免地丢失。恰好0.1+0.2计算出来的数最后一位在损失精度后不为0,所以结果为:0.300000000000000004。如果截断精度后的最后一位是0,那么自然不会出现不等的结果,比如0.1+0.6===0.7。其实0.1和0.6转换成二进制后都会损失精度,但是截取的值都是0,所以相等。也不等于0.1+0.7!==0.8等等。所以就是在计算的时候转换成二进制会损失精度,导致0.1+0.2!==0.3。JavaScript中的所有值都存储为IEEE-754标准的64位双精度浮点数。IEEE754标准中的64位双精度浮点数的小数部分最多支持53个二进制数字。由于浮点数的小数位数的限制,二进制数需要先截断,然后再转为十进制,所以在进行算术运算时会出现错误。这里可以看出,如果要将十进制小数转化为有限二进制小数,那么计算出的小数第一位必须以5结尾(因为只有0.5×2才能转化为整数)。二进制数转十进制的方法是:将二进制数分成整数部分和小数部分,分别进行转换,再组合成十进制值。整数部分:这里直接使用parseInt函数,parseInt('1011',2)=>11。小数部分:例如1011.001的小数位为001,采用下表的计算方法。小数部分001基数的幂2-12-22^-3各位与基数的乘积0×(2^-1)0×(2-2)1×(2-3)各位的乘积结果最后是000.125的结果是每比特乘积结果相加:0+0+0.125=0.125。将整数与小数相加,得到1011.001的小数:11.125。按照规则,代码实现如下:=二元结构。split('.')让binDecimal=0如果(binDecStr){binDecimal=[...binDecStr].reduce((res,val,index)=>{res+=Number(val)*(2**(-(index+1)))returnres},0)}returnparseInt(binIntStr,2)+binDecimal}