Преобразование C # побитовых операций в Javascript

#javascript #c# #bit-manipulation

#javascript #c# #манипулирование битами

Вопрос:

Я пытаюсь преобразовать следующую функцию C # в Javascript, но мне не очень повезло (см. Мою попытку ниже).

Исходный код C #:

 using System;
                    
public class Program
{
    const UInt16 MASK = 0xA001;
    public static void Main()
    {
        byte[] test = System.Text.Encoding.ASCII.GetBytes("A TEST STRING");
        ushort result = Program.GetChecksum(test); 
    }
    
    public static ushort GetChecksum(byte[] pBytes)
    {
       ushort result = 0;
       int vCount = pBytes.Length;
       byte b;
       for (int i = 0; i < vCount; i  )
       {
           b = pBytes[i];
           for (byte cnt = 1; cnt <= 8; cnt  )
           {
               if (((b % 2) != 0) ^ ((result % 2) != 0))
               {
                   result = (ushort)((result >> 1) ^ MASK);
               }
               else
               {
                   result = (ushort)(result >> 1);
               }
               b = (byte)(b >> 1);
           }
       }
       return resu<
    }
}
 

Моя попытка преобразования:

Javascript:

 const MASK = 0xA001;

const GetChecksum = (b: Buffer) => {
    const result = Buffer.alloc(10).fill(0); // Don't know how much to alloc here
    for (let i = 0; i < b.length; i  )
    {
        const byte = b[i];
        for (let j = 1; j <= 8; j  )
        {
          const t1 = (byte % 2) !== 0;
          const t2 = (result[i] % 2) !== 0;
          
          result[i] = (!(t1 amp;amp; t2) amp;amp; (t1 || t2))
            ? ((result[i] >> 1) ^ MASK) 
            : (result[i] >> 1);

          result[i] = byte >> 1;
        }
    }
    return resu<
}

const x =  GetChecksum(Buffer.from('THIS IS A TEST','ascii'));
console.log(x.toString('ascii'));
 

В частности, я не могу воспроизвести условие: (((b % 2) != 0) ^ ((result % 2) != 0)) , хотя я думаю, что в моей попытке есть несколько проблем.

Любая помощь здесь будет оценена!

Ответ №1:

Эквивалент javascript этого кода:

 const MASK = 0xA001;

function getChecksum(bytes) {
    let result = 0;                                            // this is a number not a buffer
    
    for (let b of bytes) {                                     // for each byte in bytes (clearer than 'for' with an index 'i')
        for (let ctn = 1; ctn <= 8; ctn  ) {                   // same as C#
            if (((b % 2) !== 0) ^ ((result % 2) !== 0)) {      // same as C#
               result = (result >> 1) ^ MASK;                  // same as C#
            } else {
               result = result >> 1;                           // same as C#
            }
            
            b = b >> 1;                                        // same as C#
        }
    }
    
    return resu<
};

let buffer = Buffer.from("A TEST STRING", "ascii");
let result = getChecksum(buffer);
let checksumString = result.toString(16);

console.log(checksumString);
 

Комментарии:

1. Разве вы не хотели const бы вместо let — и >>> (беззнаковый сдвиг вправо) вместо >> ?

2. @Dai result меняется для каждого байта в массиве, поэтому этого не может быть const , что касается сдвига вправо без знака, я подумаю, как только выясню, что именно делает исходный код.

3. Я имел в виду использование const for buffer и внешнего result and checksumString .

4. @Dai в использовании let для них тоже нет проблем — и сдвиг вправо без знака здесь не понадобится, потому что result , поскольку это число (намного больше, чем 16-разрядное short , используемое в коде C #), достаточно велико, чтобы большинство крайних левых битов всегда 0 были такими >> и >>> имелив этом случае результат тот же. Кроме того, текущий байт b по умолчанию беззнаковый, поэтому >>> здесь тоже ничего не изменится

Ответ №2:

Я надеюсь, что это даст вам ключ к разгадке:

 if ((((b % 2) | 0) !== 0) ^ (((result % 2) >>> 0) !== 0)) {