代码之家  ›  专栏  ›  技术社区  ›  Jithesh Kt

有没有可能把两个整数压缩成十六进制并把它们取回来

  •  2
  • Jithesh Kt  · 技术社区  · 6 年前

    我有个奇怪的要求,
    我的目的地只支持一个整数,但我想向它发送两个整数,然后我想从响应中获取它们。

    例如,

    允许输入:

     {
        'task': 2
     }
    

    我有一种微妙的逻辑在我身边,但我的目标不知道这一点。所以,在不让人知道目标的情况下,我能不能用某种方式打包两个整数,然后在将来解码?

    这可以用十六进制来实现吗?

    4 回复  |  直到 6 年前
        1
  •  3
  •   MC Emperor    6 年前

    您可以将任意两个数字组合起来,并使用它们的乘积(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

        2
  •  2
  •   RalfFriedl    6 年前

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

    假设您的任务和子任务在1到255之间。然后你可以编码

    combined = (task * 256) + subtask
    

    然后解码

    task = combined / 256
    subtask = combined % 256
    
        3
  •  2
  •   Oliver    6 年前

    首先,您不必将整数转换为十六进制。整数是一个值,而十进制、十六进制或二进制则表示该值。所以你所需要的就是整数运算来实现你的目标。

    根据这个 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整数值,但对于我们来说,它包含三个值。

    要从压缩值中获取所有三个值,我们必须从中选择正确的位。这包括两个步骤,首先移除下侧所有不需要的位(使用shift right),然后移除上侧所有不需要的位(通过掩蔽):

    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位值。只要确定每一个的最大值,并相应地设置宽度(可能添加一至三位,以确保)。

        4
  •  0
  •   Tim    6 年前

    如果不能有两个连续的数字,我不建议使用十六进制。尝试转换为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();