Last updated at
warning
この記事は最終更新から3年以上経っています。情報が古くなっている可能性が高いです。
note
2017/11/03 追記 ECMAScript Proposal Stage-3 に BigInt が入っており、これが使用可能になればネイティブで 64bit 数値でのビット演算ができるようになる。それを使えばここに書かれている事象は発生しないし、ここに書かれていることを行う必要もなくなる。
このサイトにある MoE 装備 DB では、アイテムの産出(アイテムの出どころ)属性をビットフラグで管理している。 ある日、防具装飾武器に加え飲食物データも管理できるようにしようと思いたち、4 つくらい項目(というか状態?)を増やした。 ところが追加した項目を含めようとしても(ビット OR)全くビットの状態に変化がない...。 色々調べてみた結果、Javascript、もとい ECMAScript の仕様が原因だとわかった。
ECMAScript では64 ビットの整数でもビット演算時は 32 ビットに丸められてしまう。
64bit 演算を行うためのモジュールを作成した。
//bitwise64.js
(function(root,factory){
if(typeof define==='function'&&define.amd){
define([],factory);
}elseif(typeof exports==='object'){
module.exports=factory();
}else{
root.NS=root.NS||{};
root.NS['bitwise64']=factory();
}
})(this,function(){
"use strict";
var
bit64=Math.pow(2,32),
padding='';
for(let i=0,l=64;i<l;i++)padding+='0';
var emulate=function(n,o){
var
r=Number(0),
ts=(padding+this.toString(2)).slice(-64),
tl=parseInt(ts.slice(-32),2),
th=parseInt(ts.slice(0,32),2),
ns=(padding+(Number(n)).toString(2)).slice(-64),
nl=parseInt(ns.slice(-32),2),
nh=parseInt(ns.slice(0,32),2);
r=parseInt(
(padding+(o==='&'?((th&nh)>>>0):((th|nh)>>>0)).toString(2)).slice(-32)+
(padding+(o==='&'?((tl&nl)>>>0):((tl|nl)>>>0)).toString(2)).slice(-32)
,2);
return r;
};
Number.prototype.bitAnd = function(n) {
return (this>=bit64||n>=bit64)?emulate.call(this,n,'&'):(this&n);
};
Number.prototype.bitOr = function(n) {
return (this>=bit64||n>=bit64)?emulate.call(this,n,'|'):(this|n);
};
return0;
});
XOR,NOT には未対応(力尽きた)。 Prototype 拡張してるし、かなりの力技だけど、動けばそれでいいのだ。