由于知识面不广,以前在开发游戏的时候,总觉得number(int,float啥的),就是想换一种电脑理解的方式来表达数字之间的关系的一个类型,直至最近项目涉及到超大数(想想尾部有90个0),频繁小数计算,才慢慢的踩到一些前辈们的坑,以至于我也不得不写一些文章,来警告自己的不务正业
无论是js还是ts,number作为唯一的数字类型,一直以为最大的是64位值,直至看了各大论坛后才发现,number竟然偷工减料…
1、在js和ts中(其它语言不清楚哈),number最大表示53位
2、number是有精度下限的,长度是16位(toPrecision)。
3、你可以打开IDE ,输出0.123456789123456789.toPrecision(16),里面的数值可以修改,看看效果。
如想理解更透彻
1 、双精度64位大小比较
字符串比较大小
var check=(a,b)=>{
let c= a.toString();
let d = b.toString();
return c==d;
}
这种写法怎么看怎么容易理解,即使我是个小白,我也知道它想要表达什么。 这种写法虽然同样能得出结果,但性能奇差,因为字符串是自左往右逐个比较ascci码,比到最后要是发现长度不一样,那就这趟白跑了。
高低位比较
var check=(a,b)=>{
if (n1 && n2) {
let nl1 = n1.hasOwnProperty("low") ? n1.low : n1;
let nl2 = n2.hasOwnProperty("low") ? n2.low : n2;
if (nl1 == nl2) {
let nh1 = n1.high ? n1.high : 0;
let nh2 = n2.high ? n2.high : 0;
if (nh1 == nh2) {
return true;
} else {
return false;
}
} else {
return false;
}
}
return false;
}
请教了下后端的同事(甩锅系列),觉得这种做法会比字符串好,但,怎么说呢,似乎在做手游的时候,cpu的运行总不是重要的问题,肯定会被忽略。
2、保留小数点几位的问题。
这个经常就忘记了,都要百度一下,取小数点多少位就用,留在公众号以后要用的时候能立刻找到吧:
NumberObject.toFixed(num)
不过这家伙返回来的是个字符串,要是你想把它当作数字用,那就尴尬了,你还得parseInt()一次,最最最尴尬的,这家伙返回来的是四舍五入…四舍五入你知道什么意思吗,就是5.123456toFixed(4) == 5.1235,要是遇到想用5.1234的,那就只能或者猜测,将数字转为字符串,挨个挨个的切出来,再转换为数字吧,自求多福吧!
let str = a.toString();(比如a是123)
let tstr = ""
for (let i = 0; i < str.length; i++) {
if (i < 2) {
tstr += str[i];
}
}
3、判断数字是为小数
ts似乎没有判断该数字是否为小数的方法,而我个人的做法,就是:
a - parseInt(a+"") > 0
4、NaN
NaN 即 Not a Number , 不是一个数字,number数据类型中除了浮点型和整数型还有一个特殊的值 NaN,不过人家不是一个可以确定的数值,而是表示一种范围的状态,你可以理解为:反正不是一个number,至于多少,它也不知道,所以,NaN != NaN,两个不确定的范围怎么可能勾搭到一起呢。
5、数字相加小数超多问题
在给数字进行运算的时候,总能遇到一些灵异事件,要是大半夜一个人偷偷在撸码,不知道的还以为见鬼了呢,比如:
两位数相加
0.1+0.2=0.30000000000000004;
两位数相减
1.1+0.2=0.90000000000000001;
两位数相乘
0.2*0.2=0.40000000000000001;
两位数相除
这个是亲生的,基本你想要答案都对的,如果有遇到上述的情况,麻烦通知下,我们要做到一个都不能少。
好吧,出现这么奇葩的事情,至少得弄清楚是谁搞的鬼吧,不然,自己在开发着微信小游戏,把腾讯家当成冤大头那就不好了。
寻寻觅觅,在csdn看到 vamcily 在09年发布的文章(看来,地球村没啥新鲜事哈,我在18年遇到的问题,人家09年就已经颁布天下了),总结如下:
0.1这个浮点数在二进制中无法精确表示【其实远不止0.1这个光棍】
计算机内部的所有数值计算都是基于二进制的,十进制的0.1对应的二进制是0.00001111……,后面的1无限循环,而javascript中浮点数是64位(IEEE 754标准),对位数的截断带来了精度的丢失,因此使得累加的结果超出了我们的预料
还有 北方的刀郎 :
其实对于浮点数的四则运算,几乎所有的编程语言都会有类似精度误差的问题,只不过在 C++/C#/Java 这些语言中已经封装好了方法来避免精度的问题,而 JavaScript (还有ts)是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。下面就分析下为什么会有这个精度误差,以及怎样修复这个误差。
首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:
0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)
双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100110011001100 因浮点数小数位的限制(最高16位精度)而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。
解决方法:
最简单的方法,保留小数+四舍五入先生,foFixed(2),然后再相加吧
也可以用toPrecision(12)(12精确度是链接博主的经验之谈),之后在运算
一般开发项目的时候,都会有个想保留多少位数下限(根据保留位数乘以相应的值),比如2位,那就乘以100,然后再相加,当然3位就乘以1000,再相除吧!
当然你也可以选择,用math.floor或者ceil,来切掉小数
**
## **公众号:文字曰 希望我能坚持吧!!!**
**