Có thể làm toán vectơ với hai số được đóng gói thành một. Đầu tiên hãy để tôi đưa ra một ví dụ trước khi tôi giải thích cách nó hoạt động:
let a = vec_pack([2,4]);
let b = vec_pack([1,2]);
let c = a+b; // Vector addition
let d = c-b; // Vector subtraction
let e = d*2; // Scalar multiplication
let f = e/2; // Scalar division
console.log(vec_unpack(c)); // [3, 6]
console.log(vec_unpack(d)); // [2, 4]
console.log(vec_unpack(e)); // [4, 8]
console.log(vec_unpack(f)); // [2, 4]
if(a === f) console.log("Equality works");
if(a > b) console.log("Y value takes priority");
Tôi đang sử dụng thực tế là nếu bạn chuyển hai số X lần và sau đó cộng hoặc trừ chúng trước khi chuyển chúng trở lại, bạn sẽ nhận được kết quả giống như khi bạn chưa chuyển chúng từ đầu. Tương tự, phép nhân và phép chia vô hướng hoạt động đối xứng với các giá trị được dịch chuyển.
Một số JavaScript có độ chính xác số nguyên là 52 bit (số nổi 64 bit), vì vậy tôi sẽ đóng gói một số thành 26 bit có sẵn cao hơn và một số vào số thấp hơn. Mã được làm lộn xộn hơn một chút vì tôi muốn hỗ trợ các số có chữ ký.
function vec_pack(vec){
return vec[1] * 67108864 + (vec[0] < 0 ? 33554432 | vec[0] : vec[0]);
}
function vec_unpack(number){
switch(((number & 33554432) !== 0) * 1 + (number < 0) * 2){
case(0):
return [(number % 33554432),Math.trunc(number / 67108864)];
break;
case(1):
return [(number % 33554432)-33554432,Math.trunc(number / 67108864)+1];
break;
case(2):
return [(((number+33554432) % 33554432) + 33554432) % 33554432,Math.round(number / 67108864)];
break;
case(3):
return [(number % 33554432),Math.trunc(number / 67108864)];
break;
}
}
Nhược điểm duy nhất tôi có thể thấy với điều này là x và y phải nằm trong phạm vi + -33 triệu, vì chúng phải vừa với nhau trong phạm vi 26 bit.