大数字 - JavaScript中的数学

时间:2016-06-16 21:02:32

标签: javascript math

我正在开发一款3D空间游戏,它使用了大量的数学公式,导航,缓动效果,旋转,行星之间的巨大距离,物体质量等......

我的问题是使用数学这样做的最佳方法。我应该以整数计算所有内容并获得非常大的整数(超过20位数),或使用带小数的小数字。

根据我的经验,使用带小数的数字时的数学运算不准确,在使用带小数的大数字时会导致奇怪的行为。

4 个答案:

答案 0 :(得分:3)

我会避免使用小数。他们已经知道精确度问题:http://floating-point-gui.de/

我建议使用整数,但是如果你需要使用非常大的整数,我建议使用大数或大整数库,例如其中一个:

缺点是您必须使用这些数字对象及其方法,而不是原始的Number类型和标准JS运算符,但是对于大数字操作,您将具有更大的灵活性。

修改
正如le_m指出的那样,另一个缺点是速度。库方法的运行速度不如本机运算符快。你必须自己测试,看看性能是否可以接受。

答案 1 :(得分:1)

使用JavaScript编号对象

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number

  

Number.MAX_SAFE_INTEGER   JavaScript中的最大安全整数(2 ^ 53 - 1)。

     

Number.MIN_SAFE_INTEGER   JavaScript中的最小安全整数( - (253 - 1))。

var biggestInt = 9007199254740992;
var smallestInt = -9007199254740992;

var biggestNum = Number.MAX_VALUE;
var smallestNum = Number.MIN_VALUE;
var infiniteNum = Number.POSITIVE_INFINITY;
var negInfiniteNum = Number.NEGATIVE_INFINITY;
var notANum = Number.NaN;

console.log(biggestInt); // http://www.miniwebtool.com/scientific-notation-to-decimal-converter/?a=1.79769313&b=308
console.log(smallestInt); // http://www.miniwebtool.com/scientific-notation-to-decimal-converter/?a=5&b=-32

console.log(biggestNum);
console.log(smallestNum);
console.log(infiniteNum);
console.log(negInfiniteNum);
console.log(notANum);

debugger;

我只能想象这是你的应用程序遇到更大问题的一个标志,这可能非常简单。

请阅读数字文字

http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.3

  

一旦确定了数字文字的精确MV,它就是   然后四舍五入为Number类型的值。如果MV是0,那么   舍入值为+0;否则,舍入值必须是数字   MV的值(在8.5中指定),除非文字是a   DecimalLiteral和literal有超过20位有效数字   在哪种情况下,Number值可以是MV的Number值   通过替换后的每个有效数字生成的文字   20的0位数字或文字的MV的数字值   通过用20替换20之后的每个有效数字而产生的   数字,然后在第20位有效数字处递增字面值   位置。如果数字不是ExponentPart的一部分,则数字很重要   和

     
      
  • 不是0;
  •   
  • 或左侧有一个非零数字,并且右边有一个非零数字,而不是ExponentPart。
  •   

澄清

我应该补充一点,Number Object包装器可以提供精度到100(在这个数字以上会给你一个RangeType错误)在某些浏览器中有效数字,但是大多数环境目前只实现所需的21位有效数字的精度。 / p>

通过OP原始问题阅读,我相信天际线提供了最佳答案,建议提供超过100位有效数字的库(我要通过的一些测试使用250位有效数字)。实际上,看到有人再次重振其中一个项目会很有趣。

答案 2 :(得分:1)

从太阳到半人马座的距离为4.153×10 18 cm。您可以使用Number数据类型很好地表示此值,该数据类型存储的值最大为1.7977×10 308 ,其中包含大约17个有效数字。

但是,如果你想对驻扎在半人马座阿尔法星的太空船进行建模怎么办?

由于Number的精度有限,您可以存储值4153000000000000000或4153000000000000500,但两者之间不存在任何内容。这意味着您将在Alpha Centauri上获得500厘米的最大空间分辨率。你的宇宙飞船看起来很笨重。

我们可以使用除Number之外的其他数据类型吗?当然,您可以使用BigNumber.js等库,它可以提供几乎无限精度的支持。您可以将您的太空船停放在Alpha Centauri的热核心旁边一毫米,而不会出现(数字)问题:

pos_acentauri = new BigNumber(4153000000000000000);

pos_spaceship = pos_acentauri.add(0.1); // one milimeter from Alpha Centauri

console.log(pos_spaceship); // 4153000000000000000.1
<script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/2.3.0/bignumber.min.js"></script>

然而,这艘船的船长不仅会被烧死,而且你的3D引擎也会慢得发抖。这是因为Number允许在恒定时间内进行真正快速的算术计算,而e。 G。 BigNumber加法计算时间随着存储值的大小而增加。

解决方案:将Number用于3D引擎。您可以使用不同的局部坐标系,例如: G。一个用于Alpha Centauri,一个用于我们的太阳系。只能使用BigNumber来处理HUD,游戏统计等内容。

答案 3 :(得分:0)

BigNumber的问题在于

  

使用大于15的数字文字造成的精度损失   有效数字

我的解决方案将是BigNumber和web3.js的组合:

var web3 = new Web3();
let one = new BigNumber("1234567890121234567890123456789012345");
let two =   new BigNumber("1000000000000000000");
let three = new BigNumber("1000000000000000000");
const minus = two.times(three).minus(one);
const plus = one.plus(two.times(three));
const compare = minus.comparedTo(plus);
const results = {
    minus: web3.toBigNumber(minus).toString(10),
    plus: web3.toBigNumber(plus).toString(10),
    compare
}
console.log(results); // {minus: "-234567890121234567890123456789012345", plus: "2234567890121234567890123456789012345", compare: -1}