[英]JavaScript's xor result different than the one of Java
SOLUTION 解
I had a bug in my internal conversion logic. 我的内部转换逻辑中有一个错误。
ORIGINAL QUESTION 原始问题
I need to implement an algorithm both in Java and JavaScript, whereas the Java implementation and calculation result is the reference. 我需要在Java和JavaScript中实现算法,而Java实现和计算结果是参考。 However, when invoking the XOR operator on a "negative" value (I know that Java and JavaScript make use of 2's complement) causes Java's result to be positive, whereas the JavaScript result is negative, as shown in the output below:
但是,当在“负”值上调用XOR运算符时(我知道Java和JavaScript使用2的补码)会导致Java的结果为正,而JavaScript结果为负,如下面的输出所示:
Java output:
hash A: 16777619
hash B: 637696617
hash A: 637696613
hash B: 988196095
hash A: 988196062
hash B: -1759370886
hash A: 1759370917 <-- here the JavaScript implementation behaves different
hash B: -1169850945
JavaScript output:
hash A: 16777619
hash B: 637696617
hash A: 637696613
hash B: 988196095
hash A: 988196062
hash B: -1759370886
hash A: -1759370843 <-- this result should be equal to the Java result
hash B: -1883572545
Below you can see the Java source code: 您可以在下面看到Java源代码:
private static final int FNV_PRIME = 0x1000193;
private static final int FNV_COMPRESS = 0xFFFF;
...
public long getHash(int inputNumber)
{
int hash = FNVCalculator.FNV_PRIME;
ByteBuffer intToByteArrayConverter = ByteBuffer.allocate(4);
intToByteArrayConverter.putInt(inputNumber);
byte[] inputValues = intToByteArrayConverter.array();
// inputValues.length is always equal to 4
for (byte processCounter = (byte) 0; processCounter < inputValues.length; processCounter++)
{
hash ^= inputValues[processCounter];
System.out.println("hash A: " + hash);
hash *= FNV_PRIME;
System.out.println("hash B: " + hash);
}
return (hash & FNVCalculator.FNV_COMPRESS);
}
The following snippet shows the JavaScript code: 以下代码段显示了JavaScript代码:
var Constants =
{
FNV_PRIME: parseInt("1000193", 16),
FNV_COMPRESS: parseInt("FFFF", 16),
BYTE_ARRAY_LENGTH: 4,
...
};
Object.freeze(Constants);
var hash = Constants.FNV_PRIME;
for (var counter = 0; counter < Constants.BYTE_ARRAY_LENGTH; counter++)
{
hash ^= inputNumberArray[counter];
console.log("hash A: " + hash);
// mutltiply the hash with the 32 bit FNV prime number: 2^24 + 2^8 + 0x93
// source: https://github.com/wiedi/node-fnv/blob/master/fnv.js
hash += ((hash << 24) + (hash << 8) + (hash << 7) + (hash << 4) + (hash << 1));
hash |= 0;
console.log("hash B: " + hash);
}
return (hash & Constants.FNV_COMPRESS);
The array with the numbers is equal in the Java as well as in the JavaScript version, as show below (all numbers are decimal numbers): 具有数字的数组在Java和JavaScript版本中是相等的,如下所示(所有数字都是十进制数字):
Java version:
inputValues[0]: 0
inputValues[1]: 12
inputValues[2]: 33
inputValues[3]: -33
JavaScript version:
inputNumberArray[0]: 0
inputNumberArray[1]: 12
inputNumberArray[2]: 33
inputNumberArray[3]: -33
I have already tried replacing the byte array with an integer array, but it has not helped. 我已经尝试用整数数组替换字节数组,但它没有帮助。 I'm using WebKit's JavaScriptCore engine.
我正在使用WebKit的JavaScriptCore引擎。
Seeing the values, I suspect that Java is sign extending the 223 when you convert it to a series of bytes and Javascript isn't. 看到这些值,我怀疑当你将它转换为一系列字节而Javascript不是时,Java会扩展223。 223 = 0xDF = 0xFFFFFFDF when sign extended....
符号扩展时223 = 0xDF = 0xFFFFFFDF ....
Things to be careful about when porting between Java and JavaScript. 在Java和JavaScript之间移植时要注意的事项。
Bitwise shift operators only operate on 32 bit values in Javascript. 按位移位运算符仅在Javascript中以32位值运行。 JavaScript internally represents all numbers as 64 bit floats and does not, distinguish between floats and ints as Java does.
JavaScript在内部将所有数字表示为64位浮点数,而不是像Java那样区分浮点数和整数。 Even more, JavaScript does not have int or float sizes eg there is no byte, int or long types.
更重要的是,JavaScript没有int或float大小,例如没有byte,int或long类型。
There is always a risk becoming unstuck because of the above statements and the difference in the way the languages represents numbers. 由于上述陈述以及语言代表数字的方式不同,总有风险变得不稳定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.