Javascript 的 64bit Int 支持
- 2015-09-22 更新:加入 Int64.ts 的介绍连接。
- 2017-04-28 更新:加入 Number.isSafeInteger
最近把一个 native 游戏移植到 HTML5,客户端和服务端都是 C++ ,而且游戏金币经常性超过 231 ,所以服务端的大爷们很任性地使用了 int64 。
这下问题来了,Javascript 不支持 int64 。
说服服务端的大爷们改用 32bit 是不可能的。说服大爷们使用字符串也是不可能的。说服策划重新设置数值使其小于 231 也是不可能的。
有句话怎么说的?如果不能反抗,那就默默享受吧……
看我这个 Javascript 前端菜鸟如何应对!
本着不重复(tou)造轮(lan)子的优良传统,我发现了这样几个已有的实现方案:
2个uint 拼接
lizi 这位比我还懒的程序员同学实现的 方法,这酸爽……
1package lz.jprotoc
2{
3 import flash.utils.IDataInput;
4 /**
5 * ...
6 * @author lizhi http://matrix3d.github.io/
7 */
8 public class Int64
9 {
10 public var low:uint = 0;
11 public var high:uint = 0;
12 public function Int64(low:uint=0,high:uint=0)
13 {
14 this.low = low;
15 this.high = high;
16 }
17
18 public function equal(v:Int64):Boolean {
19 if (v == null) return false;
20 return (v.low == low) && (v.high == high);
21 }
22
23 public function isZero():Boolean {
24 return low == 0 && high == 0;
25 }
26
27 public function toString():String {
28 return "high:0x" + high.toString(16)+" low:0x" + low.toString(16);
29 }
30
31 }
32}
虽然是 AS3 写的,但转成 JS 也是分分钟。
字符串拼接法
dom 同学用 ByteArray 来保存每个字节 (同样是 AS3),然后将其转成字符串来显示,缺点和上面 lizi 的一样,就是无法计算。
node-int64
node-int64 采用 Javascript 的 Number 来实现对超过 int32 的数值的保存。由于 Number 采用 双精度浮点数 来保存数值,因此该值的范围只能在 +/- 253 的范围内。
这是我最终的选择。因为金币的值在客户端是会参与计算的,但估计在游戏的有生之年都不可能大于 253 。
我基于该版本修改了一个 TypeScript 版的 Int64.ts,可以在 egret 中使用。
Number.isSafeInteger
TishoYs Space 提到了使用 Number.isSafeInteger + parseInt 来处理 Int64,需要注意几个问题:
- 如果服务器传递过来的是数字,因为字节序的问题(2个4字节),必须使用上面提到的方法来读取;如果服务器传递过来的是字符串,那么可以使用 parseInt。
- isSafeInteger 是在 ES6 加入的,在客户端要慎用。可以使用下面的代码自行实现 Number.isSafeInteger:
1Number.isSafeInteger = Number.isSafeInteger || function (value) {
2 return Number.isInteger(value) && Math.abs(value) <= Number.MAX_SAFE_INTEGER;
3};
(全文完)
- 文章ID:2363
- 原文作者:zrong
- 原文链接:https://blog.zengrong.net/post/int64-in-javascript/
- 版权声明:本作品采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可,非商业转载请注明出处(原文作者,原文链接),商业转载请联系作者获得授权。