是否可以将两个整数打包成十六进制并将其取回

时间:2018-08-10 05:15:57

标签: javascript

我有一个奇怪的要求,
我的目的地仅支持一个整数,但是我想向其发送两个整数,之后又想从响应中找回它们。

例如,

允许的输入:

 {
    'task': 2
 }

我身边有一些子任务逻辑,但是我的目标并没有意识到这一点。因此,在不通知目标的情况下,我可以以某种方式打包两个整数并在将来将其解码回来吗?

可以用十六进制实现吗?

4 个答案:

答案 0 :(得分:3)

您可以组合任意两个数字,并使用它们的乘积(a * b)重新获得两个数字,只要 a * (a * b) + b < Number.MAX_SAFE_INTEGER

这是一个演示代码段:

(() => {
  document.addEventListener("click", handleStuff);
  // formula: c = (a * (a * b)) + b
  // as long as c < 9007199254740991
  const combine = (a, b) => ({
      a: a, 
      b: b,
      get c() { return this.a * this.b; },
      get combined() { return this.a * this.c + this.b; },
      get unraveled() { return [
        Math.floor(this.combined / this.c), 
        this.combined % this.c ]; }
  });
  const log = txt => document.querySelector("pre").textContent = txt;
  let numbers = combine(
    +document.querySelector("#num1").value, 
    +document.querySelector("#num2").value );

  function handleStuff(evt) {
    if (evt.target.nodeName.toLowerCase() === "button") {
      if (evt.target.id === "combine") {
        numbers = combine(
          +document.querySelector("#num1").value, 
          +document.querySelector("#num2").value );
        if (numbers.combined > Number.MAX_SAFE_INTEGER) {
          log (`${numbers.combined} too large, unraveled will be unreliable`);
        } else {
          log (`Combined ${numbers.a} and ${numbers.b} to ${numbers.combined}`);
        }
      } else {
        log(`${numbers.combined} unraveled to ${numbers.unraveled}`);
      }
    }
  }

})();
input[type=number] {width: 100px;}
<p>
  <input type="number" id="num1" 
    value="12315" min="1"> first number
</p>
<p>
  <input type="number" id="num2" 
    value="231091" min="1"> second number
</p>
<p>
  <button id="combine">combine</button>
  <button id="unravel">unravel</button>
</p>

<pre id="result"></pre>

注意@RallFriedl启发了这个答案

JSFiddle

答案 1 :(得分:2)

是的,假设您的两个整数所包含的信息不超过一个整数可以处理的信息。

让我们假设您的任务和子任务在1..255范围内。然后您可以编码

combined = (task * 256) + subtask

然后解码

task = combined / 256
subtask = combined % 256

答案 2 :(得分:2)

首先,您不必将整数转换为十六进制即可。整数是一个值,十进制,十六进制或二进制是表示该值的表示形式。因此,您所需要做的就是整数算术来达到目标​​。

根据此answer,javascript中允许的最大整数为9007199254740991。如果用二进制形式记下来,将得到53个,这意味着整数中可以存储53位。现在,您可以根据需要将其分为两个或更多个较小的范围。

例如,假设您需要保存三个数字,第一个数字始终低4.294.967.296(32位),第二个数字始终低65.536(16位),第三个数字总是低32(5位)。如果将这三个值的所有位加起来,您将得到53位,这意味着它将完全匹配。

要将所有这些值打包为一个,只需将它们移动到整数内的正确位位置即可。在我的示例中,我想让32位数字位于最低位置,然后是16位数字,在最高位置是5位:

var max32bitValue = 3832905829; // binary: 1110 0100 0111 0101 1000 0000 0110 0101
var max16bitValue = 47313;      // binary: 1011 1000 1101 0001
var max5bitValue = 17;          // binary: 1000 1

var packedValue = max32bitValue           // Position is at bit 0, so no movement needed.
                  + max16bitValue << 32   // Move it up next to the first number.
                  + max5bitValue << 48;    // Move it up next to the second number (32 + 16)

现在可以存储该单个整数值,原因是一个完全有效的javascript整数值,但对我们而言,它具有三个值。

要从打包值中获取所有三个值,我们必须从中选择正确的位。这涉及两个步骤,首先删除下侧的所有不需要的位(通过使用右移),然后删除上侧的所有不需要的位(通过屏蔽):

var max32bitValueRead = packedValue & Math.pow(2, 32);         // No bits on the lower side, just mask the higher ones;
var max16bitValueRead = (packedValue >> 32) & Math.pow(2, 16); // Remove first 32 bits and set all bits higher then 16 bits to zero;
var max5bitValueRead = (packedValue >> 48);                    // Remove first 48 bits (32 + 16). No higher bits there, so no mask needed.

因此,希望这有助于理解如何在多个整数值不超过最大位范围的情况下将多个整数值放入一个整数中。根据您的需要,您可以在其中放入两个26位的值,或者移动一个32位和21位的值或48位和5位的值。只需确定每个数字的最大值是多少,然后相应地设置宽度即可(可以确定,可以增加一到三位)。

答案 3 :(得分:0)

如果您不能有2个连续数字,我不建议使用十六进制。尝试转换为ASCII字符,然后返回。因此,如果您想发送: { 'task': 21 } 您可以将21设置为以下字符: var a = 55; var b = String.fromCharCode(a); var send2 = { 'task': b };

并将其转换回去,将是:var res = { 'task': b }; var original = res.task.charCodeAt();