我正在开发一款3D空间游戏,它使用了大量的数学公式,导航,缓动效果,旋转,行星之间的巨大距离,物体质量等......
我的问题是使用数学这样做的最佳方法。我应该以整数计算所有内容并获得非常大的整数(超过20位数),或使用带小数的小数字。
根据我的经验,使用带小数的数字时的数学运算不准确,在使用带小数的大数字时会导致奇怪的行为。
答案 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}