在 JavaScript 中解析指数值并将其转换为十进制

Posted

技术标签:

【中文标题】在 JavaScript 中解析指数值并将其转换为十进制【英文标题】:Parsing and converting exponential values to decimal in JavaScript 【发布时间】:2013-09-10 13:05:19 【问题描述】:

我想使用 javascript 解析指数值并将其转换为小数。 4.65661287307739E-10 应该给 0.000000000465661287307739。我应该怎么做才能做到这一点?

parseFloat(4.65661287307739E-10) 返回4.65661287307739e-10

parseInt(4.65661287307739E-10) 返回4

【问题讨论】:

将其设置为num 变量并使用toFixed() codingforums.com/showthread.php?t=184468 Javascript parseFloat '1.23e-7' gives 1.23e-7 when need 0.000000123的可能重复 【参考方案1】:

你可以使用toFixed(),但有20个限制。

例如:

(4.65661287307739E-10).toFixed(20)
"0.00000000046566128731"

但是……

(4.65661287307739E-30).toFixed(20)
"0.00000000000000000000"

因此,如果您的小数位数始终少于 20 位,那就没问题了。否则,我认为您可能必须自己编写。

【讨论】:

【参考方案2】:

您可以显示大或小小数的字符串值:

Number.prototype.noExponents= function()
    var data= String(this).split(/[eE]/);
    if(data.length== 1) return data[0]; 

    var  z= '', sign= this<0? '-':'',
    str= data[0].replace('.', ''),
    mag= Number(data[1])+ 1;

    if(mag<0)
        z= sign + '0.';
        while(mag++) z += '0';
        return z + str.replace(/^\-/,'');
    
    mag -= str.length;  
    while(mag--) z += '0';
    return str + z;

var n=4.65661287307739E-10 ;
n.noExponents()

/*  returned value: (String)
0.000000000465661287307739
*/

【讨论】:

谢谢回复。我怎么知道一个数字是否是指数数字?只有当数字是指数时,我才会使用这种方法。 @B_D:如果数字的字符串值不包含e或E,则返回数字。 您的解决方案效果很好,但是像 9.52543977e3 这样的数字正在挂起浏览器。这可能需要优化。【参考方案3】:

这个变体非常适合我显示过小/大数字的格式化字符串值:

const exponentialToDecimal = exponential => 
    let decimal = exponential.toString().toLowerCase();
    if (decimal.includes('e+')) 
        const exponentialSplitted = decimal.split('e+');
        let postfix = '';
        for (
            let i = 0;
            i <
            +exponentialSplitted[1] -
                (exponentialSplitted[0].includes('.') ? exponentialSplitted[0].split('.')[1].length : 0);
            i++
        ) 
            postfix += '0';
        
        const addCommas = text => 
            let j = 3;
            let textLength = text.length;
            while (j < textLength) 
                text = `$text.slice(0, textLength - j),$text.slice(textLength - j, textLength)`;
                textLength++;
                j += 3 + 1;
            
            return text;
        ;
        decimal = addCommas(exponentialSplitted[0].replace('.', '') + postfix);
    
    if (decimal.toLowerCase().includes('e-')) 
        const exponentialSplitted = decimal.split('e-');
        let prefix = '0.';
        for (let i = 0; i < +exponentialSplitted[1] - 1; i++) 
            prefix += '0';
        
        decimal = prefix + exponentialSplitted[0].replace('.', '');
    
    return decimal;
;

const result1 = exponentialToDecimal(5.6565e29); // "565,650,000,000,000,000,000,000,000,000"
const result2 = exponentialToDecimal(5.6565e-29); // "0.000000000000000000000000000056565"

【讨论】:

以下输入"-5.1224567890e-3" 给出"0.00-51224567890"的输出【参考方案4】:

一个可怕的原始转换,用 ES6 编写:

 function convert(n)
        var sign = +n < 0 ? "-" : "",
            toStr = n.toString();
        if (!/e/i.test(toStr)) 
            return n;
        
        var [lead,decimal,pow] = n.toString()
            .replace(/^-/,"")
            .replace(/^([0-9]+)(e.*)/,"$1.$2")
            .split(/e|\./);
        return +pow < 0 
            ? sign + "0." + "0".repeat(Math.max(Math.abs(pow)-1 || 0, 0)) + lead + decimal
            : sign + lead + (+pow >= decimal.length ? (decimal + "0".repeat(Math.max(+pow-decimal.length || 0, 0))) : (decimal.slice(0,+pow)+"."+decimal.slice(+pow)))
    

var myvar = 4.951760157141521e+27;
var myvar2 = 4.951760157141521e-2;
var myvar3 = 3.3e+3;
convert(myvar);//"4951760157141521000000000000"
convert(myvar2);//"0.04951760157141521"
convert(myvar3);//"3300"

【讨论】:

所有短号都会使代码中断 e.f. convert(3.3e+3) 或任何其他 1 或 2 位数字 @MohsenAlyafei 很棒的收获!我试图修复它。你会试一试吗? 也在这里发布以供审核codereview.stackexchange.com/questions/243164/… 谢谢。希望对您有所帮助。投票将不胜感激。谢谢【参考方案5】:

这是我将指数(电子符号)数字转换为小数的简短函数代码,允许输出大量小数位

它处理 Javascript 允许的所有电子符号语法,包括以下内容:

Valid e-notation numbers in Javascript:
   123e1    ==>  1230
   123E1    ==>  1230
   123e+1   ==>  1230
   123.e+1  ==>  1230   (with missing fractional part)
   123e-1   ==>  12.3
   0.1e-1   ==>  0.01
   .1e-1    ==>  0.01   (with missing whole part)
  -123e1    ==> -1230
   0.0e1    ==>  0
  -0.0e4    ==> -0

该函数不会尝试捕获 NaN 或未定义的输入,但会尝试满足正常(非电子符号)数字;这些数字按“原样”返回。

我已尝试在每条线路上提供足够的 cmets,并尝试(尽可能!)避免使用短路和条件(三元)运算符,以提高清晰度。

我已经使用toLocaleString() 方法来自动检测小数分隔符符号,但这当然假设表示数字的输入字符串遵循机器的区域设置(尤其是手动传递给函数时)。

/********************************************************
* Converts Exponential (e-Notation) Numbers to Decimals
********************************************************
* @function numberExponentToLarge()
* @version  1.00
* @param   string  Number in exponent format.
*                   (other formats returned as is).
* @return  string  Returns a decimal number string.
* @author  Mohsen Alyafei
* @date    12 Jan 2020
*
* Notes: No check is made for NaN or undefined inputs
*
*******************************************************/

function numberExponentToLarge(numIn) 
 numIn +="";                                            // To cater to numric entries
 var sign="";                                           // To remember the number sign
 numIn.charAt(0)=="-" && (numIn =numIn.substring(1),sign ="-"); // remove - sign & remember it
 var str = numIn.split(/[eE]/g);                        // Split numberic string at e or E
 if (str.length<2) return sign+numIn;                   // Not an Exponent Number? Exit with orginal Num back
 var power = str[1];                                    // Get Exponent (Power) (could be + or -)

 var deciSp = 1.1.toLocaleString().substring(1,2);  // Get Deciaml Separator
 str = str[0].split(deciSp);                        // Split the Base Number into LH and RH at the decimal point
 var baseRH = str[1] || "",                         // RH Base part. Make sure we have a RH fraction else ""
     baseLH = str[0];                               // LH base part.

  if (power>=0)    // ------- Positive Exponents (Process the RH Base Part)
     if (power> baseRH.length) baseRH +="0".repeat(power-baseRH.length); // Pad with "0" at RH
     baseRH = baseRH.slice(0,power) + deciSp + baseRH.slice(power);      // Insert decSep at the correct place into RH base
      if (baseRH.charAt(baseRH.length-1) ==deciSp) baseRH =baseRH.slice(0,-1); // If decSep at RH end? => remove it

   else          // ------- Negative exponents (Process the LH Base Part)
     num= Math.abs(power) - baseLH.length;                               // Delta necessary 0's
     if (num>0) baseLH = "0".repeat(num) + baseLH;                       // Pad with "0" at LH
     baseLH = baseLH.slice(0, power) + deciSp + baseLH.slice(power);     // Insert "." at the correct place into LH base
     if (baseLH.charAt(0) == deciSp) baseLH="0" + baseLH;                // If decSep at LH most? => add "0"

  
  // Rremove leading and trailing 0's and Return the long number (with sign)
  return sign + (baseLH + baseRH).replace(/^0*(\d+|\d+\.\d+?)\.?0*$/,"$1");


//============ test codes ==================
function test(test,input,should)
var  out=numberExponentToLarge(input);
var r = (out===should) ? true : false;
if (!r) console.log(test+" Failed: "+out+" should be: "+should);
  else console.log("Passed");

// ------------- tests for e-notation numbers ---------------------

test(1,"123E0","123")
test(2,"123E0","123")
test(3,"-123e+0","-123")
test(4,"123e1","1230")
test(5,"123e3","123000")
test(6,"123e+3","123000")
test(7,"123E+7","1230000000")
test(8,"-123.456e+1","-1234.56")
test(9,"123.456e+4","1234560")
test(10,"123E-0","123")
test(11,"123.456e+50","12345600000000000000000000000000000000000000000000000")

test(12,"123e-0","123")
test(13,"123e-1","12.3")
test(14,"123e-3","0.123")
test(15,"-123e-7","-0.0000123")
test(16,"123.456E-1","12.3456")
test(17,"123.456e-4","0.0123456")
test(18,"123.456e-50","0.00000000000000000000000000000000000000000000000123456")
test(18-1,"-123.456e-50","-0.00000000000000000000000000000000000000000000000123456")

test(19,"1.e-5","0.00001")  // handle missing base fractional part
test(20,".123e3","123")     // handle missing base whole part

// The Electron's Mass: 
test(21,"9.10938356e-31","0.000000000000000000000000000000910938356")
// The Earth's Mass:
test(22,"5.9724e+24","5972400000000000000000000")
// Planck constant:
test(23,"6.62607015e-34","0.000000000000000000000000000000000662607015")

test(24,"0.000e3","0")
test(25,"0.000000000000000e3","0")
test(26,"-0.0001e+9","-100000")
test(27,"-0.0e1","-0")
test(28,"-0.0000e1","-0")
test(28,"-000.0000e1","-0")    // this is an invalid Javascript number
test(28,"-000.0000e-1","-0")   // this is an invalid Javascript number
test(28,"-000.0000e+10","-0")  // this is an invalid Javascript number
test(28,"-000.0000e+2","-0")   // this is an invalid Javascript number

// ------------- testing for Non e-Notation Numbers -------------
test(29,"12345.7898","12345.7898") // no exponent
test(30,12345.7898,"12345.7898")   // no exponent
test(31,0.00000000000001,"0.00000000000001")    // from 1e-14
test(32,-0.0000000000000345,"-0.0000000000000345") // from -3.45e-14
test(33,-0,"0")
test(34,"1.2000e0","1.2")
test(35,"1.2000e-0","1.2")
test(35,"1.2000e+0","1.2")
test(35,"1.2000e+10","12000000000")

【讨论】:

【参考方案6】:

使用 toFixed(number)

例如:

(+exponentialnumber).toFixed(8)


2e-7 ===> 0.00000020

【讨论】:

【参考方案7】:

从@kennebec 的答案扩展,但处理他失败的边缘情况更好(Gist, with CoffeeScript):

  String.prototype.noExponents = function(explicitNum) 
    var data, leader, mag, multiplier, num, sign, str, z;
    if (explicitNum == null) 
      explicitNum = true;
    

    /*
     * Remove scientific notation from a number
     *
     * After
     * http://***.com/a/18719988/1877527
     */
    data = this.split(/[eE]/);
    if (data.length === 1) 
      return data[0];
    
    z = "";
    sign = this.slice(0, 1) === "-" ? "-" : "";
    str = data[0].replace(".", "");
    mag = Number(data[1]) + 1;
    if (mag <= 0) 
      z = sign + "0.";
      while (!(mag >= 0)) 
        z += "0";
        ++mag;
      
      num = z + str.replace(/^\-/, "");
      if (explicitNum) 
        return parseFloat(num);
       else 
        return num;
      
    
    if (str.length <= mag) 
      mag -= str.length;
      while (!(mag <= 0)) 
        z += 0;
        --mag;
      
      num = str + z;
      if (explicitNum) 
        return parseFloat(num);
       else 
        return num;
      
     else 
      leader = parseFloat(data[0]);
      multiplier = Math.pow(10, parseInt(data[1]));
      return leader * multiplier;
    
  ;

  Number.prototype.noExponents = function() 
    var strVal;
    strVal = String(this);
    return strVal.noExponents(true);
  ;

【讨论】:

【参考方案8】:

在 ExtJS 中你可以使用 Ext.Number.toFixed(value, precision) 方法,内部使用 toFixed() 方法,

例如

console.log(Ext.Number.toFixed(4.65661287307739E-10, 10));  
// O/p => 0.0000000005

console.log(Ext.Number.toFixed(4.65661287307739E-10, 15));  
// 0.000000000465661

【讨论】:

以上是关于在 JavaScript 中解析指数值并将其转换为十进制的主要内容,如果未能解决你的问题,请参考以下文章

如何检测 JavaScript 字符串中的 URL 并将其转换为链接?

解析单元格中的文本并将其转换为多列中的数据

如何在react / javascript中处理换行符<br>并将其转换为html [重复]

如何解析 DateTime 并将其转换为 RFC 822 日期时间格式?

Bing Text-to-Speech 可以采用 javascript 变量值并将其转换为语音吗?

如何将 JSON 中的 SQL 主键转换为 javascript 对象键,并将其他数据作为其值