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

303

当JavaScript在字符串上下文中使用时,它将大于21位数的整数转换为科学计数法。我正在将整数作为URL的一部分打印出来。如何防止发生此转换?


6
您希望将1E21显示为“1000000000000000000000”吗?您关心的是数字的显示方式还是存储方式? - outis
7
我关心它的显示方式:我有一个document.write(myvariable)命令。 - chris
3
我需要数字作为URL的一部分。 - chris
9
人类用户并不是唯一想要读取数字的群体。当遇到包含科学计数法坐标的"translate"转换时,D3似乎会抛出异常。 - O. R. Mapper
5
当你处理一定范围内的数字时,仍然有使用价值。毕竟,对于不了解科学计数法的用户来说,科学计数法将很难阅读。 - hippietrail
显示剩余2条评论
28个回答

0

如果您不介意使用Lodash,它有toSafeInteger()函数。

_.toSafeInteger(3.2);
// => 3
 
_.toSafeInteger(Number.MIN_VALUE);
// => 0
 
_.toSafeInteger(Infinity);
// => 9007199254740991
 
_.toSafeInteger('3.2');
// => 3

0

我知道这已经过去很多年了,但最近我一直在处理类似的问题,我想发布我的解决方案。目前被接受的答案使用0填充指数部分,而我的尝试找到确切的答案,尽管通常对于非常大的数字来说并不完全准确,因为JS在浮点精度方面有限制。

这对于Math.pow(2, 100)有效,返回正确的值1267650600228229401496703205376。

function toFixed(x) {
  var result = '';
  var xStr = x.toString(10);
  var digitCount = xStr.indexOf('e') === -1 ? xStr.length : (parseInt(xStr.substr(xStr.indexOf('e') + 1)) + 1);
  
  for (var i = 1; i <= digitCount; i++) {
    var mod = (x % Math.pow(10, i)).toString(10);
    var exponent = (mod.indexOf('e') === -1) ? 0 : parseInt(mod.substr(mod.indexOf('e')+1));
    if ((exponent === 0 && mod.length !== i) || (exponent > 0 && exponent !== i-1)) {
      result = '0' + result;
    }
    else {
      result = mod.charAt(0) + result;
    }
  }
  return result;
}

console.log(toFixed(Math.pow(2,100))); // 1267650600228229401496703205376


@Oriol - 是的,你说得对;我猜以前我尝试过的任何东西都是由于其他因素而导致的。我会在我的答案中删除那个小注释。 - andi
1
无法正常工作:toFixed(Number.MAX_VALUE) == Number.MAX_VALUE - manonthemat
这只是偶然地适用于2的幂,因为浮点数在内存中的存储方式如此。实际上,如果你从Math.pow(2, 100)减去一些数字,它仍然会给出相同的答案。如果数字高于Number.MAX_SAFE_INTEGER= 9007199254740991,它只会失去精度。任何比这更高的数字都不会被精确存储,因此无法读取回来。 - Adassko

-1

您还可以使用 YourJS.fullNumber。例如,YourJS.fullNumber(Number.MAX_VALUE) 的结果如下所示: 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

它也适用于非常小的数字。 YourJS.fullNumber(Number.MIN_VALUE) 返回: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005

需要注意的是,此函数始终会返回有限数字作为字符串,但对于非有限数字(例如 NaNInfinity),它将返回 undefined

您可以在此处的YourJS控制台中测试它。


-1
如果你只是为了显示而这样做,你可以在数字四舍五入之前从中构建一个数组。
var num = Math.pow(2, 100);
var reconstruct = [];
while(num > 0) {
    reconstruct.unshift(num % 10);
    num = Math.floor(num / 10);
}
console.log(reconstruct.join(''));

这将返回正确的答案,但会花费很长时间,可能会导致执行超时。 - Hani

-3
function printInt(n) { return n.toPrecision(100).replace(/\..*/,""); }

存在一些问题:

  • 显示0.9为“0”
  • 显示-0.9为“-0”
  • 显示1e100为“1”
  • 仅适用于数字达到约1e99 => 对于更大的数字使用其他常量;或者对于优化使用较小的数字。

1
是的,那些确实是一些问题。 - Adam Leggett

-4
你可以使用 number.toString(10.1):
console.log(Number.MAX_VALUE.toString(10.1));

注意:目前此功能在Chrome中可用,但在Firefox中不可用。规范要求基数必须是整数,因此这会导致不可靠的行为。

这到底是干什么的?10.1的基数? - joniba
这个不起作用。自ES5以来,实现必须在参数上使用ToInteger。因此,使用10.110或什么都不使用是等效的。 - Oriol
是的,最近确实已经停止工作了。有点难过,但这个答案现在已经不相关了。 - zamfofex

-5
如果你想将科学计数法转换为整数: parseInt("5.645656456454545e+23", 10) 结果:5

1
仅仅取小数点前面的所有内容与将科学计数法转换为自然数值无关。 - René Baudisch

-7

我曾经遇到过Oracle返回科学计数法的问题,但是我需要实际数字用于URL。我使用了PHP的一个技巧,通过减去零来获得正确的数字。

例如5.4987E7就是这个值。

newval = val - 0;

newval现在等于54987000


2
这没有影响。5.4987E7的指数小于21,因此无论何时转换为字符串,它都会显示完整的数字。(5.4987E21 - 0).toString() => "5.4987e+21" - Dwight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接