二进制基础知识

209 阅读7分钟

计算机中的数值表示

  • 进位计数制两大要素
    • 基数R
    • 位权W

进制转换

二进制转十进制

  • 方法: 按权展开,加权求和,以(111.11)2为例

img

十进制转二进制

  • 整数部分: 除2取余,直到商为0,最先得到的余数是最低位,最后得到的余数是最高位.
  • 小数部分: 乘2取整,直到积为0或者达到精度要求为止,最先得到的整数是高位
  • 例如 (7.75)10=(111.11)2

img

img

计算机中的数据

  • 数据
    • 数值数据
      • 无符号数据
      • 有符号数据
    • 数值数据
      • 文字
      • 图像

无符号数据的表示

  • 原码: 3个bit能表示8个数 0 1 2 3 4 5 6 7

img

有符号数据的表示

原码

无法用加法表示减法

  • 原码: 3个bit能表示8个数 +0 +1 +2 +3 -0 -1 -2 -3
  • 符号: 用0、1表示正负号,放在数值的最高位

img

反码

可以用加法表示减法

  • 反码:正数不变,负数的除符号位外取反

img

补码

计算机里只有补码

  • 补码:正数不变,负数在反码的基础上加1

img

小数

小数点表示

  • 在计算机中,小数点及其位置是隐含规定的,小数点并不占用存储空间
  • 定点数: 小数点的位置是固定不变的
  • 浮点数:小数点的位置是会变化的

定点小数

  • 定点小数: 小数点隐含固定在最高数据位的左边,整数位则用于表示符号位,用于表示纯小数. 例如: (0.110011)2

img

定点整数

  • 定点整数: 小数点位置隐含固定在最低位之后,最高位为符号位,用于表示纯整数.
  • 例如: (0110011.)2

img

浮点数

  • 对于既不是定点整数,也不是定点小数的数用浮点数表示
  • 在计算机中通常把浮点数N分成阶码尾数两部分来表示
  • 小数点位置由阶码规定,因此是浮动的
  • N=尾数*基数阶码,基中尾数是一个规格化的纯小数
  • 例如8位系统中,阶码占3位,尾数占3位,数符和阶符各占1位
  • (3.5)10=(11.1)2=0.111*210
  • 科学记数法是一种记数的方法。把一个数表示成a与10的n次幂相乘的形式,可以节约空间和时间
  • 例如:(1≤|a|<10,n为整数),比如 1100= 1.1x103

IEEE754标准

  • JavaScript采用的是双精度(64位)
  • 符号位决定了一个数的正负,指数部分决定了数值的大小,小数有效位部分决定了数值的精度
  • 一个数在 JavaScript 内部实际的表示形式 (-1)符号位1.有效位2指数位
  • 精度最多53个二进制位, -(253-1)到253-1
  • 指数部分最大值是 2017(211-1),分一半表示负数,JavaScript能够表示的数值范围是21024~2-102

img

img

0.1+0.2 =0.3问题

精度丢失问题,两个不精确的数相加,结构也是不精确的

  • 十进制的0.1,实际上是二进制的0.000110(一直无限循环0110)
  • 十进制的0.2,实际上是二进制的0.00110(一直无限循环0110)
  • 得到的十进制0.3,也是一直循环0110

image-20240512214041488

0.1+0.3 == 0.4 // 结果是true
因为十进制的0.1,转成二进制后是无限小数
十进制的0.3,转成二进制后是无限小数
相加得到的数字,在IEEE754标准的精度就是相等的

JS大数相加

  • 列竖式方法 从低位向最高位计算的,注意进位

    // 大数相加
    function add(a, b) {
      let len = Math.max(a.length, b.length)
      // 把两个数对齐,不足的位 位数补0
      a = a.padStart(len, '0')
      b = b.padStart(len, '0')
    
      let result = ''
      // 进位
      let carry = 0
      for (let i = len - 1; i >= 0; i--) {
        // 从末尾开始相加(字符串转数字)
        const sum = +a[i] + b[i] + carry
        // 位数相加大于0,保留个位,位数进1
        const ge = sum % 10
        // 拿到进位的1
        carry = Math.floor(sum / 10)
        result = ge + result
      }
      return result
    }
    
    let a = '123456789'
    let b = '23456789'
    console.log(add(a, b))
    

ArrayBuffer

  • ArrayBuffer对象用来表示通用的、固定长度的原始二进制数据缓冲区
  • 它是一个字节数组,通常在其他语言中称为byte array
  • 你不能直接操作 ArrayBuffer 的内容,而是要通过类型数组对象TypedArrayDataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

bytearray

//创建一个长度为8个字节的buffer,8个字节,64位
const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength);

TypedArray

TypedArray对象描述了一个底层的二进制数据缓冲区(binary data buffer)的一个类数组视图(view)

  • 但它本身不可以被实例化,甚至无法访问,你可以把它理解为接口,它有很多的实现
类型单个元素值的范围大小(bytes)描述
Int8Array-128 to 12718 位二进制有符号整数
Uint8Array0 to 25518 位无符号整数
Int16Array-32768 to 32767216 位二进制有符号整数
Uint16Array0 to 65535216 位无符号整数

TypedArray

const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength);//8
const int8Array = new Int8Array(buffer);
console.log(int8Array.length);//8 元素的长度,1个字节占8个位

// 每16位表示1个字节
const int16Array = new Int16Array(buffer);
console.log(int16Array.length);//4

DataView对象

  • DataView视图是一个可以从二进制ArrayBuffer对象中读写多种数值类型的底层接口
  • setInt8()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个8-bit数(一个字节)
  • getInt8()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个8-bit数(一个字节)
new DataView(buffer [, byteOffset [, byteLength]])

DataView

const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength);//8个字节
const view1 = new DataView(buffer);
view1.setInt8(0, 1); 
console.log(view1.getInt8(0));//1

view1.setInt8(1, 2); 
console.log(view1.getInt8(1));//2

console.log(view1.getInt16(0));//258

Blob

  • Blob对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

  • Blob() 构造函数返回一个新的 Blob 对象。 blob的内容由参数数组中给出的值的串联组成。

  • FileReader

    对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

    • readAsText():读取文本文件(可以使用txt打开的文件),返回文本字符串,默认编码是UTF-8
    • readAsDataURL():读取文件获取一段以data开头的字符串,这段字符串的本质就是DataURL,DataURL是一种将文件嵌入到文档的方案。DataURL是将资源转换为base64编码的字符串形式,并且将这些内容直接储存在url中
  • 构造函数

    var aBlob = new Blob( array, options );
    
    • array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings会被编码为UTF-8。

    • options 是一个可选的

      BlobPropertyBag
      

      字典

      • type 默认值为 "",它代表了将会被放入到blob中的数组内容的MIME类型
<body>
    <script>
     let debug = { name: "zhufeng" };
     let str = JSON.stringify(debug);
     console.log("str", str);

     var blob = new Blob([str], { type: "application/json" });
     console.log("blob.size", blob.size);

        function readBlob(blob, type) {
            return new Promise((resolve) => {
                const reader = new FileReader();
                reader.onload = function (event) {
                    resolve(event.target.result);
                };
                switch (type) {
                    case "ArrayBuffer":
                        reader.readAsArrayBuffer(blob);
                        break;
                    case "DataURL": // 二进制数据转成可读的字符串 base64字符串
                        reader.readAsDataURL(blob);
                        break;
                    case "Text":
                        reader.readAsText(blob,'UTF-8');
                        break;
                    default:
                        break;
                }
            });
        }
        readBlob(blob, "ArrayBuffer").then((buffer) => {
            console.log("buffer", buffer);
        });
        readBlob(blob, "DataURL").then((base64String) => {
            console.log("base64String", base64String);
        });
        readBlob(blob, "Text").then((text) => {
            console.log("text", text);
        });
    </script>
</body>

Object URL

可以使用浏览器新的 API URL 对象通过方法生成一个地址来表示 Blob 数据
格式为 blob:<origin>/<uuid>
URL.createObjectURL 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
revokeObjectURL 静态方法用来释放一个之前已经存在的、通过调用 URL.createObjectURL() 创建的 URL 对象
<body>
    <button onclick="download()">下载json</button>
    <script>
     function download () {
        let debug = { hello: "world" };
        let str = JSON.stringify(debug);
        var blob = new Blob([str], { type: 'application/json' });
        let objectURL = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.download = 'hello.json';
        a.rel = 'noopener';
        a.href = objectURL;
        a.dispatchEvent(new MouseEvent('click'));
        // 销毁,防止内存泄漏
        URL.revokeObjectURL(objectURL);
     }
    </script>
</body>