Endianness issue with Javascript bitwise shift left

huangapple go评论97阅读模式
英文:

Endianness issue with Javascript bitwise shift left

问题

我正在尝试将这个简单的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]

我在哪里出错了?我认为可能与字节序有关,但我不知道如何一致地处理这种问题。

英文:

I am trying to translate this simple function from Go to Javascript:

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

	output := make([]byte, l)

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

	return output
}

My first attempt was this:

function makeEmpty(size) {
  

  var result = [];
  
  for (var i = 0; i &lt; size; i++) {
    result.push(0x00);
  }
  
  return result;
  
}

function shiftLeft (b) {
  
  var len = b.length;
  
  if (len == 0) {
    throw &#39;shiftLeft requires a non-empty buffer&#39;;
  }
  
  var output = makeEmpty(len);
  
  var overflow = 0;
  
  for (var i = len - 1; i &gt;= 0; i--) {
    output[i] = b[i] &lt;&lt; 1;
    output[i] |= overflow;
    overflow = (b[i] &amp; 0x80) &gt;&gt; 7;
  }
  
  return output;
  
}

However, this does not work. Given the following test case:

function fromOctal(str) {

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

  return bytes;

}

console.log(shiftLeft(fromOctal(&quot;10000000&quot;))

The Javascript version returns [256], but the expected result is "00000000" or [0].

What am I getting wrong here? I think it might have to do with endianness, but I have no idea about how to deal with this kind of issue consistently.

答案1

得分: 2

你的错误在于假设数组的元素是8位整数,但是在JavaScript中,位运算符的结果是32位整数,因此当你进行左移操作时,最高位仍然保留。

我认为通过修改以下代码:

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

为:

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

可以解决你的问题。

http://jsfiddle.net/MTj63/

另外,我认为你的fromOctal()函数实际上应该被命名为fromBinary()

英文:

Your mistake appears to be in assuming that the elements of your array are 8-bit integers, but the result of bitwise operators in JavaScript are 32-bit integers and so the most significant bit remains when you do the left shift.

I believe that adding a bit mask by changing:

output[i] = b[i] &lt;&lt; 1;

to:

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

should fix your issue.

http://jsfiddle.net/MTj63/

As a side note, I think your fromOctal() function should actually be named fromBinary().

huangapple
  • 本文由 发表于 2014年4月10日 08:46:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/22976621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定