计算机中的数值表示
- 进位计数制两大要素
- 基数R
- 位权W
进制转换
二进制转十进制
- 方法: 按权展开,加权求和,以(111.11)2为例
十进制转二进制
- 整数部分: 除2取余,直到商为0,最先得到的余数是最低位,最后得到的余数是最高位.
- 小数部分: 乘2取整,直到积为0或者达到精度要求为止,最先得到的整数是高位
- 例如 (7.75)10=(111.11)2
计算机中的数据
- 数据
- 数值数据
- 无符号数据
- 有符号数据
- 数值数据
- 文字
- 图像
- 数值数据
无符号数据的表示
- 原码: 3个bit能表示8个数 0 1 2 3 4 5 6 7
有符号数据的表示
原码
无法用加法表示减法
- 原码: 3个bit能表示8个数 +0 +1 +2 +3 -0 -1 -2 -3
- 符号: 用0、1表示正负号,放在数值的最高位
反码
可以用加法表示减法
- 反码:正数不变,负数的除符号位外取反
补码
计算机里只有补码
- 补码:正数不变,负数在反码的基础上加1
小数
小数点表示
- 在计算机中,小数点及其位置是隐含规定的,小数点并不占用存储空间
- 定点数: 小数点的位置是固定不变的
- 浮点数:小数点的位置是会变化的
定点小数
- 定点小数: 小数点隐含固定在最高数据位的左边,整数位则用于表示符号位,用于表示纯小数. 例如: (0.110011)2
定点整数
- 定点整数: 小数点位置隐含固定在最低位之后,最高位为符号位,用于表示纯整数.
- 例如: (0110011.)2
浮点数
- 对于既不是定点整数,也不是定点小数的数用浮点数表示
- 在计算机中通常把浮点数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
0.1+0.2 =0.3问题
精度丢失问题,两个不精确的数相加,结构也是不精确的
- 十进制的0.1,实际上是二进制的0.000110(一直无限循环0110)
- 十进制的0.2,实际上是二进制的0.00110(一直无限循环0110)
- 得到的十进制0.3,也是一直循环0110
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的内容,而是要通过类型数组对象TypedArray或DataView对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
//创建一个长度为8个字节的buffer,8个字节,64位
const buffer = new ArrayBuffer(8);
console.log(buffer.byteLength);
TypedArray
TypedArray对象描述了一个底层的二进制数据缓冲区(binary data buffer)的一个类数组视图(view)
- 但它本身不可以被实例化,甚至无法访问,你可以把它理解为接口,它有很多的实现
| 类型 | 单个元素值的范围 | 大小(bytes) | 描述 |
|---|---|---|---|
| Int8Array | -128 to 127 | 1 | 8 位二进制有符号整数 |
| Uint8Array | 0 to 255 | 1 | 8 位无符号整数 |
| Int16Array | -32768 to 32767 | 2 | 16 位二进制有符号整数 |
| Uint16Array | 0 to 65535 | 2 | 16 位无符号整数 |
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]])
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-8readAsDataURL():读取文件获取一段以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>