电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

一文帶你搞懂JavaScript中的進制與進制轉(zhuǎn)換

瀏覽:115日期:2022-06-01 10:02:11
目錄
  • 進制介紹
  • 進制轉(zhuǎn)換
    • parseInt(str, radix)
    • Number()
    • +(一元運算符)
    • Number.prototype.toString(radix)
  • 自定義轉(zhuǎn)換
    • 十進制與十六進制轉(zhuǎn)換
    • 十進制和二進制轉(zhuǎn)換

進制介紹

JavaScript 中提供的進制表示方法有四種:十進制、二進制、十六進制、八進制。

對于數(shù)值字面量,主要使用不同的前綴來區(qū)分:

  • 十進制(Decimal):取值數(shù)字 0-9;不用前綴。
  • 二進制(Binary):取值數(shù)字 01 ;前綴 0b0B
  • 十六進制(Hexadecimal):取值數(shù)字 0-9a-f ;前綴 0x0X
  • 八進制(Octal):取值數(shù)字 0-7 ;前綴 0o0O (ES6規(guī)定)。

需要注意的是,非嚴格模式下瀏覽器支持:如果有前綴0并且后面只用到 0-7 八個數(shù)字的數(shù)值時,該數(shù)值視為八進制;但如果前綴0后面跟隨的數(shù)字中有 8或者9,則視為十進制。

嚴格模式下,如果數(shù)字加前綴0,則報錯:Uncaught SyntaxError: Decimals with leading zeros are not allowed in strict mode。

各進制的數(shù)值,如果取值數(shù)字超過給定的范圍,則會報錯:Uncaught SyntaxError: Invalid or unexpected token。

在JavaScript內(nèi)部的默認情況下,二進制、十六進制、八進制字面量數(shù)值,都會自動轉(zhuǎn)為十進制進行運算。

0x22 // 34
0b111 // 7
0o33 // 27
0x22 + 0b111 // 41
0o33 + 12 // 39
(0x33).toString() // 51
(0x33).valueOf() // 51

除了十進制是Javascript默認的數(shù)字進制以外,其他三種進制方式平時使用較少,主要在處理Blob數(shù)據(jù)、字節(jié)編碼或者位運算、轉(zhuǎn)義字符等等時候才會碰到。

進制轉(zhuǎn)換

下文將主要討論進制轉(zhuǎn)換時的問題。

JavaScript 提供了原生函數(shù),進行十進制與其他各進制之間的相互轉(zhuǎn)換。

其中,從其他進制轉(zhuǎn)換成十進制,有三種方式:parseInt()Number()+(一元運算符)。這三種方式都只能轉(zhuǎn)換整數(shù)。

從十進制轉(zhuǎn)換成其他進制,可以使用 Number.prototype.toString()。支持小數(shù)。

parseInt(str, radix)

第一個參數(shù)是需要解析的字符串;其他進制不加前綴。

第二個參數(shù)是一個進制基數(shù),表示轉(zhuǎn)換時按什么進制來理解這個字符串,默認值10,表示轉(zhuǎn)十進制。

第二個參數(shù)如果非數(shù)字,則自動轉(zhuǎn)數(shù)字,如無法轉(zhuǎn)稱數(shù)字則忽略該參數(shù);是數(shù)字時,必須是 2-36 的整數(shù),超出該范圍,返回 NaN

parseInt("1111", 2) // 15
parseInt("1234", 8) // 668
parseInt("18af", 16) // 6319
parseInt("1111") // 1111

如果不傳入第二參數(shù),則 parseInt 會默認使用十進制來解析字符串;但是,如果字符串以 0x 開頭,會被認為是十六進制數(shù)。

而其他進制的字符串,0o21(八進制)0b11(二進制) 不會以該進制基數(shù)自動轉(zhuǎn)換,而是得到 0

所以,在使用 parseInt 進行進制轉(zhuǎn)換時,為了保證運行結(jié)果的正確性和穩(wěn)定性,第二個參數(shù)不能省略

parseInt("0x21") // 33
parseInt("0o21") // 0
parseInt("0b11") // 0
parseInt("111", "add") // 111
parseInt("111", "787") // NaN

如果需要解析的字符串中存在對于當前進制基數(shù)無效的字符,則會從最高位取有效字符進行轉(zhuǎn)換,沒有效字符則返回NaN

parseInt("88kk", 16) // 136,=== 0x88
parseInt("kk", 16) // NaN

Number()

可以把字符串轉(zhuǎn)為數(shù)字,支持其他進制的字符串,默認轉(zhuǎn)成十進制數(shù)字。

字符串中如果存在無效的進制字符時,返回 NaN

記住,需要使用進制前綴,0b0o0x

Number("0b11100") // 28
Number("0o33") // 27
Number("0x33") //51

Number("0x88kk") // NaN

+(一元運算符)

Number() 一樣,可以把字符串轉(zhuǎn)為數(shù)字,支持其他進制的字符串,默認轉(zhuǎn)成十進制數(shù)字。

字符串中如果存在無效的進制字符時,返回 NaN

也需要使用進制前綴。

+"0b11100" // 28
+"0o33" // 27
+"0x33" //51

+"0x88kk" // NaN

可以看到,基本和 Number() 是一樣的,也在本質(zhì)上是對數(shù)字的一種轉(zhuǎn)換處理。

Number.prototype.toString(radix)

它支持傳入一個進制基數(shù),用于將數(shù)字轉(zhuǎn)換成對應進制的字符串,它支持轉(zhuǎn)換小數(shù)

未指定默認值為 10,基數(shù)參數(shù)的范圍 2-36,超過范圍,報錯:RangeError。

15..toString(2) // 1111
585..toString(8) // 1111
4369..toString(16) // 1111
(11.25).toString(2) // 1011.01

自定義轉(zhuǎn)換

除了這些原生函數(shù)以外,也可以自己實現(xiàn)進制數(shù)字之間的轉(zhuǎn)換函數(shù)。

根據(jù)相應的規(guī)則,就可以實現(xiàn)十進制與二進制、十六進制之間的轉(zhuǎn)換的一些方法。

十進制與十六進制轉(zhuǎn)換

以下代碼是針對整數(shù)在十進制與十六進制之間的轉(zhuǎn)換,根據(jù)基本規(guī)則進行換算。

十六進制是以 0-9a-f 進行描述數(shù)字的一種方式,其中 0-9 取本身數(shù)字的值,而 a-f 則取 10-15 的值。

且字母不區(qū)分大小寫。

function int2Hex (num = 0) {
  if (num === 0) {
    return "0"
  }
  const HEXS = "0123456789abcdef"
  let hex
  while (num) {
    hex = HEXS.charAt(num % 16) + hex
    num = Math.floor(num / 16)
  }
  return hex
}
function hex2Int (hex = "") {
  if (typeof hex !== "string" || hex === "") {
    return NaN
  }
  const hexs = [...hex.toLowerCase()]
  let resInt = 0
  for (let i = 0; i < hexs.length; i++) {
    const hv = hexs[i]
    let num = hv.charCodeAt() < 58 ? +hv : ((code - 97) + 10)
    resInt = resInt * 16 + num
  }
  return resInt
}

如果要轉(zhuǎn)換八進制,實際上與十六進制很類似,只需根據(jù)八進制的數(shù)值范圍進行部分改動即可。

八進制一般使用非常少,不單獨列出。

下面將重點介紹二進制轉(zhuǎn)換的相關(guān)知識,包括小數(shù)的二進制表示與轉(zhuǎn)換。

十進制和二進制轉(zhuǎn)換

在十進制與二進制的轉(zhuǎn)換中,我們將考慮小數(shù),理解小數(shù)是如何在這兩者之間進行轉(zhuǎn)換。

先選定一個數(shù)字,比如:11.125 ,我們看下該數(shù)字在二進制里的表示:

(11.125).toString(2) // 1011.001

可以看到,11.125 的二進制表示為:1011.001。下面將以這個數(shù)字為例進行轉(zhuǎn)換操作。

十進制數(shù)字轉(zhuǎn)換成二進制

首先需要了解的是,二進制小數(shù)的表示方法是如何得來的:

整數(shù) 部分,用二進制表示可以如此計算,數(shù)字 11

11 / 2 ———— 1
5 / 2 ———— 1
2 / 2 ———— 0
1 / 2 ———— 1

整數(shù)部分的規(guī)則,得到的結(jié)果是 從下往上,倒著排 1011 就是二進制的 11

小數(shù) 用二進制表示可以如此計算,小數(shù) 0.125

0.125 × 2 = 0.25 ———— 0
0.25 × 2 = 0.5 ———— 0
0.5 × 2 = 1 ———— 1

只有等于1時才結(jié)束,如果結(jié)果不等于1將會一直循環(huán)下去。小數(shù)部分的規(guī)則,得到的結(jié)果是 從上往下,順著排 0.001 就是二進制的 0.125

整數(shù) + 小數(shù),所以 11.125 的二進制表示方式:1011.001

根據(jù)以上整數(shù)和小數(shù)分開計算的規(guī)則,就可以得到一個十進制轉(zhuǎn)二進制的函數(shù),如下:

function c10to2 (num) {
  // 整數(shù)
  const numInteger = Math.floor(num)
  // 小數(shù)
  const numDecimal = num - numInteger

  let integers = []
  if (numInteger === 0) {
    integers = ["0"]
  } else {
    let integerVal = numInteger
    while(integerVal !== 1) {
      integers.push(integerVal % 2 === 0 ? "0" : "1")
      integerVal = Math.floor(integerVal / 2)
    }
    integers.push("1")
  }
  const resInteger = integers.reverse().join("")

  let decimals = []
  if (numDecimal) {
    let decimalVal = numDecimal
    // 最多取49位的長度
    let count = 49
    while (decimalVal !== 1 && count > 0) {
      decimalVal = decimalVal * 2
      if (decimalVal >= 1) {
decimals.push("1")
if (decimalVal > 1) {
  decimalVal = decimalVal - 1
}
      } else {
decimals.push("0")
      }
      count--
    }
  }
  const resDecimal = decimals.join("")

  return resInteger + (resDecimal ? ("." + resDecimal) : "")
}

小數(shù)在轉(zhuǎn)換成二進制時,會存在無限循環(huán)的問題,上面的代碼里截取了前49個值。

所以,這里就會引出了一個問題,就是常見的一個數(shù)字精度問題:0.1 + 0.2 != 0.3

0.1+ 0.2 != 0.3

直接看一下 0.1 轉(zhuǎn)二進制:

0.1 × 2 = 0.2
0.2 × 2 = 0.4
0.4 × 2 = 0.8
0.8 × 2 = 1.6
0.6 × 2 = 1.2
0.2 × 2 = 0.4 // 循環(huán)開始
0.4 × 2 = 0.8
0.8 × 2 = 1.6
0.6 × 2 = 1.2
...
...

無限循環(huán)

0.2 轉(zhuǎn)二進制:

0.2 × 2 = 0.4
0.4 × 2 = 0.8
0.8 × 2 = 1.6
0.6 × 2 = 1.2
0.2 × 2 = 0.4 // 循環(huán)開始
0.4 × 2 = 0.8
0.8 × 2 = 1.6
0.6 × 2 = 1.2
...
... 無限循環(huán)

因為無法得到1,可以發(fā)現(xiàn)有限十進制小數(shù), 0.1 轉(zhuǎn)換成了無限二進制小數(shù) 0.00011001100...0.2 轉(zhuǎn)成了 0.001100110011...

由于無限循環(huán),必然會導致精度丟失,正好 0.1 + 0.2 計算得到的數(shù)字在丟失精度后的最后一位不為0,所以導致結(jié)果為:0.30000000000000004

如果截取精度后最后一位為0,那自然就不存在結(jié)果不相等的情況,如 0.1 + 0.6 === 0.7,事實上,0.1和0.6轉(zhuǎn)二進制后都會丟失精度,但截取到的數(shù)值都是0,所以相等。

同樣不相等的還設有 0.1 + 0.7 !== 0.8等等。

所以是計算時轉(zhuǎn)二進制的精度丟失,才導致的 0.1 + 0.2 !== 0.3

在 JavaScript 中所有數(shù)值都以 IEEE-754 標準的 64 bit 雙精度浮點數(shù)進行存儲的。 IEEE 754 標準的 64 位雙精度浮點數(shù)的小數(shù)部分最多支持53位二進制位。 因浮點數(shù)小數(shù)位的限制而需要先截斷二進制數(shù)字,再轉(zhuǎn)換為十進制,所以在進行算術(shù)計算時會產(chǎn)生誤差。

這里能看到,如果十進制小數(shù)要被轉(zhuǎn)化為有限二進制小數(shù),那么它計算后的小數(shù)第一位數(shù)必然要是 5 結(jié)尾才行(因為只有 0.5 × 2 才能變?yōu)檎麛?shù))。

二進制數(shù)字轉(zhuǎn)換成十進制

方法是:將二進制分成整數(shù)和小數(shù)兩部分,分別進行轉(zhuǎn)換,然后再組合成結(jié)果的十進制數(shù)值。

整數(shù)部分:這里直接使用 parseInt 函數(shù),parseInt('1011', 2) => 11

小數(shù)部分:如 1011.001 的小數(shù)位 001,使用下表的計算方式。

小數(shù)部分001基數(shù)的位數(shù)次冪2^-12^-22^-3每位與基數(shù)乘積0 × (2^-1)0 × (2^-2)1×(2^-3)每位乘積結(jié)果000.125

最后的結(jié)果是每位乘積結(jié)果相加:0 + 0 + 0.125 = 0.125

整數(shù)與小數(shù)合起來,就得到了 1011.001 的十進制數(shù)字:11.125

根據(jù)規(guī)則,代碼實現(xiàn)如下所示:

function c2To10 (binaryStr = "") {
  if (typeof binaryStr !== "string" || binaryStr === "") {
    return NaN
  }
  const [ binIntStr, binDecStr ] = binaryStr.split(".")
  let binDecimal = 0
  if (binDecStr) {
    binDecimal = [...binDecStr].reduce((res, val, index) => {
      res += Number(val) * (2 ** (-(index + 1)))
      return res
    }, 0)
  }
  return parseInt(binIntStr, 2) + binDecimal
}

到此這篇關(guān)于一文帶你搞懂JavaScript中的進制與進制轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)JavaScript進制轉(zhuǎn)換內(nèi)容請搜索以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持!

標簽: JavaScript
主站蜘蛛池模板: 贵州水玻璃_-贵阳花溪闽兴水玻璃厂 | 艾乐贝拉细胞研究中心 | 国家组织工程种子细胞库华南分库 | SOUNDWELL 编码器|电位器|旋转编码器|可调电位器|编码开关厂家-广东升威电子制品有限公司 | POM塑料_PBT材料「进口」聚甲醛POM杜邦原料、加纤PBT塑料报价格找利隆塑料 | 风信子发稿-专注为企业提供全球新闻稿发布服务 | 能耗监测系统-节能监测系统-能源管理系统-三水智能化 | 卷筒电缆-拖链电缆-特种柔性扁平电缆定制厂家「上海缆胜」 | 波纹补偿器_不锈钢波纹补偿器_巩义市润达管道设备制造有限公司 | 全自动五线打端沾锡机,全自动裁线剥皮双头沾锡机,全自动尼龙扎带机-东莞市海文能机械设备有限公司 | 壹作文_中小学生优秀满分作文大全 | 工业废水处理|污水处理厂|废水治理设备工程技术公司-苏州瑞美迪 今日娱乐圈——影视剧集_八卦娱乐_明星八卦_最新娱乐八卦新闻 | 爆破器材运输车|烟花爆竹运输车|1-9类危险品厢式运输车|湖北江南专用特种汽车有限公司 | 土壤养分检测仪_肥料养分检测仪_土壤水分检测仪-山东莱恩德仪器 大型多片锯,圆木多片锯,方木多片锯,板材多片锯-祥富机械有限公司 | 泰兴市热钻机械有限公司-热熔钻孔机-数控热熔钻-热熔钻孔攻牙一体机 | 传爱自考网_传爱自学考试网 | 河南正规膏药生产厂家-膏药贴牌-膏药代加工-修康药业集团官网 | 成都中天自动化控制技术有限公司 | 米顿罗计量泵(科普)——韬铭机械 | 网站制作优化_网站SEO推广解决方案-无锡首宸信息科技公司 | 阿尔法-MDR2000无转子硫化仪-STM566 SATRA拉力试验机-青岛阿尔法仪器有限公司 | 布袋除尘器-单机除尘器-脉冲除尘器-泊头市兴天环保设备有限公司 布袋除尘器|除尘器设备|除尘布袋|除尘设备_诺和环保设备 | 西门子代理商_西门子变频器总代理-翰粤百科| Akribis直线电机_直线模组_力矩电机_直线电机平台|雅科贝思Akribis-杭州摩森机电科技有限公司 | 欧美日韩国产一区二区三区不_久久久久国产精品无码不卡_亚洲欧洲美洲无码精品AV_精品一区美女视频_日韩黄色性爱一级视频_日本五十路人妻斩_国产99视频免费精品是看4_亚洲中文字幕无码一二三四区_国产小萍萍挤奶喷奶水_亚洲另类精品无码在线一区 | 钢格板|镀锌钢格板|热镀锌钢格板|格栅板|钢格板|钢格栅板|热浸锌钢格板|平台钢格板|镀锌钢格栅板|热镀锌钢格栅板|平台钢格栅板|不锈钢钢格栅板 - 专业钢格板厂家 | 隔爆型防爆端子分线箱_防爆空气开关箱|依客思 | 变位机,焊接变位机,焊接变位器,小型变位机,小型焊接变位机-济南上弘机电设备有限公司 | 丹佛斯变频器-丹佛斯压力开关-变送器-广州市风华机电设备有限公司 | 拉曼光谱仪_便携式|激光|显微共焦拉曼光谱仪-北京卓立汉光仪器有限公司 | 微型实验室真空泵-无油干式真空泵-微型涡旋耐腐蚀压缩机-思科涡旋科技(杭州)有限公司 | 恒温恒湿试验箱_高低温试验箱_恒温恒湿箱-东莞市高天试验设备有限公司 | 楼承板-开口楼承板-闭口楼承板-无锡海逵 | 精雕机-火花机-精雕机 cnc-高速精雕机-电火花机-广东鼎拓机械科技有限公司 | 电缆隧道在线监测-智慧配电站房-升压站在线监测-江苏久创电气科技有限公司 | 气动机械手-搬运机械手-气动助力机械手-山东精瑞自动化设备有限公司 | 水厂自动化|污水处理中控系统|水利信息化|智慧水务|智慧农业-山东德艾自动化科技有限公司 | 嘉兴泰东园林景观工程有限公司_花箱护栏 | 云杂志网-学术期刊-首页 | 插针变压器-家用电器变压器-工业空调变压器-CD型电抗器-余姚市中驰电器有限公司 | 胜为光纤光缆_光纤跳线_单模尾纤_光纤收发器_ODF光纤配线架厂家直销_北京睿创胜为科技有限公司 - 北京睿创胜为科技有限公司 | 全钢实验台,实验室工作台厂家-无锡市辰之航装饰材料有限公司 |