【问题标题】:Endianness issue with Javascript bitwise shift leftJavascript按位左移的字节顺序问题
【发布时间】:2014-04-10 00:46:01
【问题描述】:

我正在尝试将这个简单的函数从 Go 转换为 Javascript:

func ShiftLeft(b []byte) []byte {
    l := len(b)
    if l == 0 {
        panic("shiftLeft requires a non-empty buffer.")
    }

    output := make([]byte, l)

    overflow := byte(0)
    for i := int(l - 1); i >= 0; i-- {
        output[i] = b[i] << 1
        output[i] |= overflow
        overflow = (b[i] & 0x80) >> 7
    }

    return output
}

我的第一次尝试是这样的:

function makeEmpty(size) {


  var result = [];

  for (var i = 0; i < size; i++) {
    result.push(0x00);
  }

  return result;

}

function shiftLeft (b) {

  var len = b.length;

  if (len == 0) {
    throw 'shiftLeft requires a non-empty buffer';
  }

  var output = makeEmpty(len);

  var overflow = 0;

  for (var i = len - 1; i >= 0; i--) {
    output[i] = b[i] << 1;
    output[i] |= overflow;
    overflow = (b[i] & 0x80) >> 7;
  }

  return output;

}

但是,这不起作用。给定以下测试用例:

function fromOctal(str) {

  var bytes = [parseInt(str, 2)];

  return bytes;

}

console.log(shiftLeft(fromOctal("10000000"))

Javascript 版本返回[256],但预期结果是“00000000”或[0]

我在这里做错了什么?我认为这可能与字节序有关,但我不知道如何始终如一地处理此类问题。

【问题讨论】:

    标签: javascript go bitwise-operators endianness


    【解决方案1】:

    您的错误似乎在于假设您的数组元素是 8 位整数,但是 the result of bitwise operators in JavaScript are 32-bit integers 并且当您进行左移时,最高有效位仍然存在。

    我相信通过更改添加位掩码:

    output[i] = b[i] << 1;
    

    到:

    output[i] = (b[i] << 1) & 0xFF;
    

    应该可以解决您的问题。

    http://jsfiddle.net/MTj63/

    附带说明一下,我认为您的 fromOctal() 函数实际上应该命名为 fromBinary()

    【讨论】:

    • 谢谢!有没有更“一致”的方式来处理这些问题?是否可以全面使用 TypedArrays?
    • 我不会对原始二进制数据做太多的工作,尤其是在 JavaScript 中,所以我可能不是最好的人选,但我肯定会建议研究一下 ArrayBuffer s 和Uint8Arrays 必须提供,因为它们是专门为您似乎正在做的事情而设计的。 html5rocks.com/en/tutorials/webgl/typed_arrays
    • 我怀疑使用Uint8Array 会有所帮助——IIRC 在使用按位运算符时它被转换回 32 位整数(JavaScript 实际上没有单独的数字类型,它只是意味着它在内部存储为该类型)。
    • @OneKitten 我认为你不正确。类型化数组的全部意义在于提供类型化值的数组,文章指出“类型化数组是一块内存,其中包含类型化视图”。它们不能改变位运算符的行为,但是当一个值被分配给数组时,将使用正确的位数。试试这个:var a = new Uint8Array(2); a[0] = 0x88; a[0] = a[0] &lt;&lt; 1; console.log(a[0]);,你会发现显示的值是16,而不是272
    • @JLRishe:我明白你的意思了(将在 5 分钟内删除两个 cmets)。
    猜你喜欢
    • 2020-01-13
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 2013-01-21
    • 1970-01-01
    相关资源
    最近更新 更多