如何在JavaScript中避免使用大数字的科学表示法?

如何在JavaScript中避免使用大数字的科学表示法?,javascript,Javascript,当整数变大时,JavaScript将大整数转换为科学符号。如何防止这种情况发生?使用.toPrecision、.toFixed等。您可以通过使用.toString将数字转换为字符串,然后查看其.length来计算数字中的位数。有,但如果数字>=1e21且最大精度为20,则使用科学记数法。除此之外,你可以自己滚,但会很混乱 function toFixed(x) { if (Math.abs(x) < 1.0) { var e = parseInt(x.toString().sp

当整数变大时,JavaScript将大整数转换为科学符号。如何防止这种情况发生?

使用.toPrecision、.toFixed等。您可以通过使用.toString将数字转换为字符串,然后查看其.length来计算数字中的位数。

有,但如果数字>=1e21且最大精度为20,则使用科学记数法。除此之外,你可以自己滚,但会很混乱

function toFixed(x) {
  if (Math.abs(x) < 1.0) {
    var e = parseInt(x.toString().split('e-')[1]);
    if (e) {
        x *= Math.pow(10,e-1);
        x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
    }
  } else {
    var e = parseInt(x.toString().split('+')[1]);
    if (e > 20) {
        e -= 20;
        x /= Math.pow(10,e);
        x += (new Array(e+1)).join('0');
    }
  }
  return x;
}

我对oracle返回科学符号也有同样的问题,但我需要url的实际数字。我只是使用了一个PHP技巧,通过减去零,我得到了正确的数字

例如,5.4987E7是val

newval = val - 0;

newval现在等于54987000

您可以循环数字并实现舍入

//在给定索引处替换字符的功能

//循环数字开始


这就是我最后用来从输入中获取值的方法,将数字扩展到小于17位,并将指数数字转换为x10y


我知道这是多年以后的事了,但我最近一直在研究一个类似的问题,我想发布我的解决方案。目前被接受的答案用0填充指数部分,我的答案试图找到准确的答案,尽管由于JS在浮点精度方面的限制,一般来说,对于非常大的数字,它并不完全准确

这适用于Math.pow2100,返回正确的值1267650600228229401496703205376

函数toFixedx{ var结果=; var xStr=x.toString10; var digitCount=xStr.indexOf'e'=-1?xStr.length:parseIntxStr.substrxStr.indexOf'e'+1; 对于变量i=1;i 0&&index!==i-1{ 结果='0'+结果; } 否则{ 结果=mod.charAt0+结果; } } 返回结果; }
console.logtoFixedMath.pow2100;//1267650600228229401496703205376对于小数字,如果您知道需要多少位小数,可以使用toFixed,然后使用regexp删除尾随的零

Number(1e-7).toFixed(8).replace(/\.?0+$/,"") //0.000
您可以使用number.ToString 10.1:


注意:这目前适用于Chrome,但不适用于Firefox。规范规定基数必须是整数,因此这会导致不可靠的行为。

还有一种可能的解决方案:

function toFix(i){
 var str='';
 do{
   let a = i%10;
   i=Math.trunc(i/10);
   str = a+str;
 }while(i>0)
 return str;
}

以下是我的方法的简短变体,可用于任何数字:

Number.prototype.toFixedSpecial=函数n{ var str=this.toFixedn; 如果str.indexOf'e+'=-1 返回str; //若数字采用科学记数法,则选择基数和幂 str=str.replace'',.split'e+'。reducefunctionb,p{ 返回b+Arrayp-b.length+2.0; }; 如果n>0 str+='.+Arrayn+1.0; 返回str; }; console.log 1e21.toFixedSpecial2;//1000000000000000000000.00 console.log 2.1e24.toFixedSpecial0;//2100000000000000000000000 console.log 1234567..toFixedSpecial1;//1234567 console.log 1234567.89.toFixedSpecial3;//1234567.890你的问题:

number :0x68656c6c6f206f72656f
display:4.9299704811152646e+23
您可以使用以下选项:

用于任意精度十进制和非十进制算法的JavaScript库

像这样:

let ten =new BigNumber('0x68656c6c6f206f72656f',16);
console.log(ten.toString(10));
display:492997048111526447310191

如果您只是为了显示而这样做,那么可以在数字四舍五入之前从数字构建一个数组

var num = Math.pow(2, 100);
var reconstruct = [];
while(num > 0) {
    reconstruct.unshift(num % 10);
    num = Math.floor(num / 10);
}
console.log(reconstruct.join(''));

其他人的答案并没有给出确切的数字! 此函数精确计算所需的数字并以字符串形式返回,以防止javascript更改它! 如果您需要一个数值结果,只需将函数的结果乘以第一

function toNonExponential(value) {
    // if value is not a number try to convert it to number
    if (typeof value !== "number") {
        value = parseFloat(value);

        // after convert, if value is not a number return empty string
        if (isNaN(value)) {
            return "";
        }
    }

    var sign;
    var e;

    // if value is negative, save "-" in sign variable and calculate the absolute value
    if (value < 0) {
        sign = "-";
        value = Math.abs(value);
    }
    else {
        sign = "";
    }

    // if value is between 0 and 1
    if (value < 1.0) {
        // get e value
        e = parseInt(value.toString().split('e-')[1]);

        // if value is exponential convert it to non exponential
        if (e) {
            value *= Math.pow(10, e - 1);
            value = '0.' + (new Array(e)).join('0') + value.toString().substring(2);
        }
    }
    else {
        // get e value
        e = parseInt(value.toString().split('e+')[1]);

        // if value is exponential convert it to non exponential
        if (e) {
            value /= Math.pow(10, e);
            value += (new Array(e + 1)).join('0');
        }
    }

    // if value has negative sign, add to it
    return sign + value;
}

以下解决方案绕过了非常大和非常小的数字的自动指数格式。这是一个错误修正:它不适用于非常小的负数

函数numberToStringnum { 设numStr=Stringnum; 如果Math.absnum<1.0 { 设e=parseIntnum.toString.split'e-'[1]; 如果e { 设负=num<0; 如果负数*=-1 num*=Math.pow10,e-1; numStr='0.+new Arraye.join'0'+num.toString.substring2; 如果为负numStr=-+numStr; } } 其他的 { 设e=parseIntnum.toString.split'+'[1]; 如果e>20 { e-=20; num/=Math.pow10,e; numStr=num.toString+newarraye+1.加入'0'; } } 返回numStr; } //测试。。。 console.lognumberToString+0.0000000000001; console.lognumberToString-0.0000000000001; 控制台.lognumberToString+314564649798762418795;
console.lognumberToString-314564649798762418795 我尝试使用字符串形式,而不是数字,这似乎奏效了。我只在Chrome上测试过,但它应该是通用的:

function removeExponent(s) {
    var ie = s.indexOf('e');
    if (ie != -1) {
        if (s.charAt(ie + 1) == '-') {
            // negative exponent, prepend with .0s
            var n = s.substr(ie + 2).match(/[0-9]+/);
            s = s.substr(2, ie - 2); // remove the leading '0.' and exponent chars
            for (var i = 0; i < n; i++) {
                s = '0' + s;
            }
            s = '.' + s;
        } else {
            // positive exponent, postpend with 0s
            var n = s.substr(ie + 1).match(/[0-9]+/);
            s = s.substr(0, ie); // strip off exponent chars            
            for (var i = 0; i < n; i++) {
                s += '0';
            }       
        }
    }
    return s;
}

目前,还没有分解科学符号的原生函数。但是,为此,您必须编写自己的功能

这是我的:

function dissolveExponentialNotation(number)
{
    if(!Number.isFinite(number)) { return undefined; }

    let text = number.toString();
    let items = text.split('e');

    if(items.length == 1) { return text; }

    let significandText = items[0];
    let exponent = parseInt(items[1]);

    let characters = Array.from(significandText);
    let minus = characters[0] == '-';
    if(minus) { characters.splice(0, 1); }
    let indexDot = characters.reduce((accumulator, character, index) =>
    {
        if(!accumulator.found) { if(character == '.') { accumulator.found = true; } else { accumulator.index++; } }
        return accumulator;
    }, { index: 0, found: false }).index;

    characters.splice(indexDot, 1);

    indexDot += exponent;

    if(indexDot >= 0 && indexDot < characters.length - 1)
    {
        characters.splice(indexDot, 0, '.');
    }
    else if(indexDot < 0)
    {
        characters.unshift("0.", "0".repeat(-indexDot));
    }
    else
    {
        characters.push("0".repeat(indexDot - characters.length));
    }

    return (minus ? "-" : "") + characters.join("");
}

我想可能会有几个类似的答案,但有一件事我知道 催促

注意:这仅与javascript数学函数一样精确,并且在for循环之前的行上使用log而不是log10时存在问题;它将把1000写在base-10中,作为000,所以我将它改为log10,因为人们无论如何都会使用base-10


这可能不是一个非常精确的解决方案,但我很自豪地说,它可以成功地跨基数转换数字,并带有逗号选项

我知道这是一个较老的问题,但最近表现活跃

您可以使用选项格式化输出

注: Number.toLocaleString在16位小数后四舍五入,以便

const myNumb = 586084736227728377283728272309128120398;
console.log( myNumb.toLocaleString('fullwide', { useGrouping: false }) );
…返回

5860847362772840000000000000000000

如果准确度对预期结果很重要,这可能是不可取的。

您可以使用模块。它重量轻,经过充分测试

import fromExponential from 'from-exponential';

fromExponential(1.123e-10); // => '0.0000000001123'

您还可以使用YourJS.fullNumber。例如,YourJS.fullNumberNumber.MAX_值会产生以下结果: 17976931348623157000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

它也适用于非常小的数字。YourJS.fullNumberNumber.MIN_值返回以下内容: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005

需要注意的是,此函数始终将有限数作为字符串返回,但将非有限数(如NaN或无穷大)作为未定义返回

你可以在实验室里测试一下

有一些问题:

0.9显示为0 -0.9显示为-0 1e100显示为1 仅适用于~1e99=>以下的数字使用其他常量表示更大的数字;或更小以进行优化。
破坏正则表达式。这没有精度问题,代码也不多

函数toPlainStringnum{ return++num.replace/-?\d*\.?\d*e[+-]\d+/,, 函数,b,c,d,e{ 返回e<0 ?b+0.+Array1-e-c.length.JOIN 0+c+d :b+c+d+Arraye-d.长度+1.0; }; } 控制台。logtoPlainString12345e+12; 控制台。logtoPlainString12345e+24; 控制台:logtoPlainString-12345e+24; console.logtoPlainString12345e-12; console.logtoPlainString123e-12; console.logtoPlainString-123e-12; console.logtoPlainString-123.45e-56; 控制台。logtoPlainString'1e-8';
控制台。logtoPlainString'1.0e-8' 这篇文章的问题是避免使用e符号数字,并将数字作为普通数字

因此,如果只需要将e科学符号数字转换为普通数字,包括分数,而不损失准确性,然后,必须避免使用Math对象和其他javascript数字方法,以便在处理大数字和大分数时不会发生舍入,这通常是由于二进制格式的内部存储而发生的

以下函数将e科学符号数字转换为普通数字,包括处理大数字和大分数的分数,但不会丢失准确性,因为它不使用内置的数学和数字函数来处理或操作数字

该函数还处理普通数字,因此可以将怀疑为“e”表示法的数字传递给该函数进行修复

该函数应使用不同的区域设置小数点

提供了94个测试用例

对于大的电子符号数字,将数字作为字符串传递

示例:

eToNumber("123456789123456789.111122223333444455556666777788889999e+50");
// output:
"12345678912345678911112222333344445555666677778888999900000000000000"
Javascript中的有效电子符号编号包括以下内容:

/****************************************************************** *将电子符号数字转换为普通数字 ****************************************************************** *@函数eToNumbernumber *@version 1.00 *@param{e nottation Number}指数格式的有效数字。 *将数字作为字符串传递给非常大的“e”数字或大分数 *无“e”号按原样返回。 *@return{string}一个十进制数字字符串。 *@作者Mohsen Alyafei *@日期2020年1月17日 *注:不检查NaN或未定义的输入编号。 * *****************************************************************/ 耳垂功能{ 让符号=; num+=.charAt0==-&&num=num.substring1,符号=-; 设arr=num.split/[e]/ig; 如果arr.length<2,返回符号+num; 设dot=.1.tolocalString.substr1,1,n=arr[0],exp=+arr[1]; 设w=n=n.replace/^0+/,.replacedot, pos=n.splitdot[1]?n.indexOfdot+exp:w.length+exp, L=位置-w.长度,s=+BigIntw; w=exp>=0?


L>=0?s+0.repeatL:r:pos由于某种原因,toPrecision不起作用。如果您尝试:window.examplenum=135235632462361346,然后说alertwindow.examplenum.toPrecision20,它不会弹出一个警报实际上它有时会弹出显示科学符号,而其他时候它根本不会弹出。我做错了什么?这两种建议方法对大数字或小数字都不起作用。2e64.toString将返回2e+64,因此.length无效。是否希望1E21显示为“10000000000000000000”?您关心的是数字的显示方式还是存储方式?我关心的是数字的显示方式:我有一个文档。writemyvariable命令我需要数字作为文档的一部分URL@outis:想要读取数字的不仅仅是人类用户。D3在遇到包含科学记数法坐标的转换时似乎会抛出一个异常。在处理达到一定大小的数字时,这仍然是有用的。对于那些根本不懂科学记数法的用户来说,科学记数法是很难理解的。你的解决方案给了我一个与wolframalpha截然不同的2^1000的结果。有指针吗?@Shane:这个问答是关于将浮点数显示为以10为基数的整数,而不是处理转换为以10为基数时无法以浮点格式表示的数字。你需要一个图书馆,正如在最后一行中提到的。@PeterOlson:看起来我遗漏了一个Math.abs。谢谢你的提示。toFixedNumber.MAX_VALUE==Number.MAX_VALUE应该会返回true,但是它不会…实际上,这段代码对于非常小的负数不起作用:toFixed-1E-20->0.0000000000000000000.0999999999999999999999这没有效果。5.4987E7的指数小于21,因此无论何时转换为字符串,它都显示为整数。5.4987E21-0.toString=>5.4987e+21这到底是干什么的?基数为10.1?这行不通。自ES5以来,实现需要在参数上使用ToInteger。所以使用10.1或10或什么都不使用是等效的。是的,这确实在最近有点停止工作了。有点悲哀,但这个答案现在无关紧要了。@Oriol-是的,你是对的;我猜我之前尝试过的任何东西,都是由于其他因素而产生的结果。我将删除答案中的小注释。不起作用:toFixedNumber.MAX_VALUE==Number.MAX_VALUE这只是意外地对2的幂起作用,因为浮点数就是这样保存在内存中的。事实上,如果你从Math.pow2100中减去一些数字,它仍然会给出相同的答案。如果该数字高于number.MAX_SAFE_INTEGER=9007199254740991,则会丢失精度。任何高于此值的数字都无法精确存储,因此无法读取back@manonthemat当然,它们并不相等,因为第一个是格式化字符串,第二个是数字。如果将第一个值转换为一个数字,您将看到它们是绝对相等的:。你可以收回你的否决票:Pfair够了。。。。我只是注意到我不能,除非您正在编辑答案。最好也用空字符串替换任何尾随的.0。当我尝试console.log2.2e307.toFixedSpecial10时,我得到了一个有点奇怪的值。我是说。。。我得到了几个尾随的零。反正是向上投票,因为这似乎最接近我需要的。@peter.petrov是的,您有.0000000000,因为您指定了10作为参数。如果你想摆脱它们,请使用0,注意bignumber.js不能超过15位有效数字…关于此代码唯一答案的一些附加信息可能会有用。添加到函数中的注释。问题文字上要求使用大数字请小心避免将0作为固定调用的参数-它最终将擦除重要的尾随零:1000.toFixed0.replace/\.?0+$/,//1,而不是1000这不会保留原始值…例如31415926535897932384626433832795变为3141592658938480804080406626264不是正数,但可能与JavaScript处理大数的方式有关。@domsson基本上是因为应用了IEEE浮点数算法。Javascript中的数字实际上表示为浮点数和十进制数,没有本机整数的精确类型。您可以在此处阅读更多内容:@zero\u cool任何大于number.MAX\u SAFE\u INTEGER的数字都可能出现此问题。numberToString0.0000002 0。00000019999999999999998@raphadko这就是臭名昭著的Javascript浮点精度问题,这是在JS中使用数字时另一个完全不同的痛苦。。。例如,这将返回正确的答案,但会花费很多时间,可能最终导致执行超时。这是一个简单的答案。这在PhantomJS 2.1.1中不起作用-它仍然以科学记数法结束。在Chrome中很好。这似乎对非常小的小数不起作用:var myNumb=0.0000000001;console.log myNumb.toLocaleString'fullwide',{useGrouping:false};您可以设置maximumSignificantDigits选项Max21T
o格式化非常小的小数,即:js console.log myNumb.toLocaleString'fullwide',{useGrouping:true,maximumSignificantDigits:6};maximumFractionDigits默认为3,所以我认为实际的sol'n是value.toLocaleString'fullwide',{useGrouping:false,maximumFractionDigits:20}这对于非常大的数字来说是失败的。我尝试了2830869077153280555654708118725434445169156730,得到了2830869077153280500000000000000000000000000000000000000000000000000是的,这些是一些问题。这适用于引用的普通数字、未引用的普通数字、引用的科学记数法和未引用的科学记数法。@otterslide修订。仍然是一个问题。Try:console.logtoPlainString1e-5;console.logtoPlainString1e-6;console.logtoPlainString1e-7;1e-7突然跳到小数点后8位,尽管1、2、3、4、5、6都可以。@Mohsenalyafi-0.toString返回0,我不想在这里扩展科学符号。这需要显式测试-0或使用toLocalString/Intl.NumberFormat@mohsenalyyafei 0==-0函数在某些数字上失败。请看我上面帖子中的测试用例。谢谢
function dissolveExponentialNotation(number)
{
    if(!Number.isFinite(number)) { return undefined; }

    let text = number.toString();
    let items = text.split('e');

    if(items.length == 1) { return text; }

    let significandText = items[0];
    let exponent = parseInt(items[1]);

    let characters = Array.from(significandText);
    let minus = characters[0] == '-';
    if(minus) { characters.splice(0, 1); }
    let indexDot = characters.reduce((accumulator, character, index) =>
    {
        if(!accumulator.found) { if(character == '.') { accumulator.found = true; } else { accumulator.index++; } }
        return accumulator;
    }, { index: 0, found: false }).index;

    characters.splice(indexDot, 1);

    indexDot += exponent;

    if(indexDot >= 0 && indexDot < characters.length - 1)
    {
        characters.splice(indexDot, 0, '.');
    }
    else if(indexDot < 0)
    {
        characters.unshift("0.", "0".repeat(-indexDot));
    }
    else
    {
        characters.push("0".repeat(indexDot - characters.length));
    }

    return (minus ? "-" : "") + characters.join("");
}
// If you're gonna tell me not to use 'with' I understand, just,
// it has no other purpose, ;( andthe code actually looks neater
// 'with' it but I will edit the answer if anyone insists
var commas = false;

function digit(number1, index1, base1) {
    with (Math) {
        return floor(number1/pow(base1, index1))%base1;
    }
}

function digits(number1, base1) {
    with (Math) {
        o = "";
        l = floor(log10(number1)/log10(base1));
        for (var index1 = 0; index1 < l+1; index1++) {
            o = digit(number1, index1, base1) + o;
            if (commas && i%3==2 && i<l) {
                o = "," + o;
            }
        }
        return o;
    }
}

// Test - this is the limit of accurate digits I think
console.log(1234567890123450);
const myNumb = 1000000000000000000000;
console.log( myNumb ); // 1e+21
console.log( myNumb.toLocaleString() ); // "1,000,000,000,000,000,000,000"
console.log( myNumb.toLocaleString('fullwide', {useGrouping:false}) ); // "1000000000000000000000"
const myNumb = 586084736227728377283728272309128120398;
console.log( myNumb.toLocaleString('fullwide', { useGrouping: false }) );
import fromExponential from 'from-exponential';

fromExponential(1.123e-10); // => '0.0000000001123'
function printInt(n) { return n.toPrecision(100).replace(/\..*/,""); }
eToNumber("123456789123456789.111122223333444455556666777788889999e+50");
// output:
"12345678912345678911112222333344445555666677778888999900000000000000"
eToNumber("123.456123456789123456895e-80");
// output:
"0.00000000000000000000000000000000000000000000000000000000000000000000000000000123456123456789123456895"
eToNumber("123456789123456789.111122223333444455556666777788889999e-50");
// output:
"0.00000000000000000000000000000000123456789123456789111122223333444455556666777788889999"
123e1   ==> 1230
123E1   ==> 1230
123e+1  ==> 1230
123.e+1 ==> 1230
123e-1  ==> 12.3
0.1e-1  ==> 0.01
.1e-1   ==> 0.01
-123e1  ==> -1230