一、0.1+0.2为什么不等于0.3?
/*
@1 十进制转换为二进制的计算 n.toString(2)
+ 整数部分
+ 小数部分
@2 JS使用Number类型表示数字(整数和浮点数),遵循IEEE-754标准 通过64位二进制值来表示一个数字
https://babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html
第0位:符号位,0表示正数,1表示负数 S
第1位到第11位「11位指数」:储存指数部分 E
第12位到第63位「52位尾数」:储存小数部分(即有效数字)F
注:尾数部分在规约形式下第一位默认为1(省略不写)
@3 最大安全数字「16位」 Number.MAX_SAFE_INTEGER === Math.pow(2,53)-1
@4 怎么解决精度问题?
+ 将数字转成整数「扩大系数」
+ 三方库:Math.js 、decimal.js、big.js ...
*/
// JS中有关于小数(浮点数)的计算会出现精准度丢失的问题
// + JS中所有值都是以2进制在计算机底层进行存储的{浮点数转为二进制,可能出现无限循环的情况}
// + 在计算机底层存储的时候,最多存储64位「舍弃了一些值,值本身就失去了精准度」
// 浮点数计算的解决方案:
// @1 toFixed保留小数点后面N位,他自己会四舍五入
例如: (0.1+0.2).toFiexed(2) 值为'0.3'
+(0.1+0.2).toFiexed(2) 值为0.3
// @2 扩大系数法
const coefficient = function coefficient(num) {
num = num + '';
let [, char = ''] = num.split('.'),
len = char.length;
return Math.pow(10, len); //-> 10**len
};
const plus = function plus(num1, num2) {
num1 = +num1;
num2 = +num2;
if (isNaN(num1) || isNaN(num2)) return NaN;
let max = Math.max(coefficient(num1), coefficient(num2));
return (num1 * max + num2 * max) / max;
};
console.log(plus(0.1, 0.2));
二、问a等于什么 使值相等
// 利用==比较会转换数据类型,而对象转数字会经历一个详细步骤「Symbol.toPrimitive->valueOf->toString...」
/*
var a = {
i: 0,
[Symbol.toPrimitive]() {
// this->a
return ++this.i;
}
};
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
*/
/*
var a = [1, 2, 3];
a.toString = a.shift;
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
*/
/*
// 全局上下文中,获取a的值:首先看VO(G)中有没有,没有再继续去GO(window)中查找
var i = 0;
Object.defineProperty(window, 'a', {
get() {
return ++i;
}
});
if (a === 1 && a === 2 && a === 3) {
console.log('OK');
}
*/
三、底层存储机制
浏览器打开页面时,首先会从计算机虚拟内存分配出两块内存出来
+ 栈内存 Stack (ECStack) 作用: 1. 供代码执行 2.存储声明的变量和原始值类型的值
- 堆内存 Heap 作用:存储对象类型的值
堆栈内存处理:↓
全局上下文中的一点问题(查找顺序):↓
先去EO(G)中找,再去GO去重
var声明的再GO中 ,let const声明的再EO(G)中
函数底层处理机制:↓