宝塔服务器面板,一键全能部署及管理,送你10850元礼包,点我领取

为啥要弄这玩意?

最近做数值游戏,需要用到很大的数字,在前端大数字会自动变成e的科学计数法。

例如123456789123456789123456789保存到localStorage时,会变成  1.2345678912345679e+26

有啥问题?

问题:

1. 在传递给服务端时,服务端因为不能处理大数字(怎么就处理不了?!),就想要我传字符串给他,

    但是大数字会变成科学计数法的字符串”4e+23″之类给服务端,而不是”400000000000000…”理想的数字字符串。

2. 在保存本地localStorage时,因为key-value的值只能是字符串,所以把num.toString()后也会变成科学计数法保存。

    例如123456789123456789123456789保存到localStorage时,会变成  1.2345678912345679e+26

3. 尝试去github、csdn找BigDecimal之类的处理大数字的Javascript或Typescript版本,但是用不了。

在常规H5里还好, 但是放到微信小游戏里就不行,会Decimal is not defined之类, 增加了window和修改wx.config配置文件也不行。急死个人哎。

解决方案:

1. 因为调试第三方库死活调不通,反正数值游戏在大数值以后,小数就非常微乎其微了,损失一些小数字也无所谓。而且项目急着上线,卧槽加班到很晚。

2. 于是写了下面的一个很搓的方法。判断e的数量,来手动给数字字符串+”0″  = =!

一个很搓的转换函数

    /**
     * 将数字转成字符串,可以转换超过16位的大数字,但是会丢失精度
     * @param value 数字
     */
    public getNumberToString(value: number) {
        let str = value.toString();
        //大于16位,用e表示的大数字,需要转换
        if (str.indexOf("e") != -1) {
            //e位置
            let eIndex = str.indexOf("e");
            //小数点位置
            let pIndex = str.indexOf(".");
            //是否有小数点, 400000000...这样的数是没有小数点的
            let bHavePoint = pIndex;
            //小数点位置
            pIndex = (pIndex == -1) ? 0 : pIndex;
            //小数点后的数字位数
            let small = eIndex - pIndex - 1;
            //e前面的数字
            let result = str.substr(0, eIndex);
            //如果e前面数字有小数点,则去掉小数点
            if (bHavePoint != -1) {
                result = result.replace(".", "");
            }
            //e后面的数字
            let eNum = str.substr(eIndex + 2, str.length);
            //需要添加的0数量
            let len = parseInt(eNum) - small;
            for (let i = 0; i < len; i++) {
                result += "0";
            }
            //返回最终结果
            return result;
        }else{
            //不是大数字,则直接返回
            return value.toString();
        }

    }

  

实际应用

  protected createGameScene(): void {
        //小型数字,正确返回
        let a: number = 3000000;
        console.log(a.toString());               //3000000
        console.log(this.getNumberToString(a));  //3000000

        //大数字,后面数字有损
        let b:number = 123456789123456789123456789;   
        console.log(b.toString());               //1.2345678912345679e+26
        console.log(this.getNumberToString(b));  //123456789123456790000000000

        //大数字,无小数点,正确返回
        let c:number = 90000000000000000000000000000; 
        console.log(c.toString());               //9e+28
        console.log(this.getNumberToString(c));  //90000000000000000000000000000
        
        //大数字字符串 parseInt还原成 数字
        let d:number = parseInt(this.getNumberToString(c));
        console.log(d);  //9e+28

        //大数字字符串 parseFloat还原成 数字
        let e:number = parseFloat(this.getNumberToString(c));
        console.log(e);  //9e+28

        //科学计数法字符串  parseInt还原成数字  这里不能使用parseInt来还原科学计数法的字符串,会错误
        let f:number = parseInt(c.toString());
        console.log(f);  //9     

        //科学计数法字符串 parseFloat还原成数字 正确
        let g:number = parseFloat(c.toString());
        console.log(g);  //9e+28
    }