我在客户端有一棵树,用javascript:
function Node(uuid, someData, versionNum) {
this.uuid = uuid;
this.someData = someData;
this.versionNum = versionNum;
this.childNodes = [];
}
和服务器中的同一棵树,在java中:
public class Node {
UUID uuid;
String someData;
int versionNum;
List<Node> childNodes;
}
客户端将每五秒向服务器发送一个请求,询问树的哈希值。我们的想法是树的散列将以递归方式计算:
public static long hashSubtree(Node node) {
long hash = node.uuid.getMostSignificantBits() ^ node.uuid.getLeastSignificantBits() ^ node.versionNum;
for (Node childNode : node.childNodes)
hash ^= hashSubtree(childNode);
return hash;
}
在客户端上,一旦收到服务器的响应,使用服务器的计算哈希,客户端就会计算出自己的本地树哈希值:
function hashSubtree(node) {
var hash = getMostSignificantBitsAsInt(node.uuid) ^ getLeastSignificantBitsAsInt(node.uuid) ^ node.versionNum;
for (var i = 0; i < node.childNodes.length; i++)
hash ^= hashSubtree(node.childNodes[i]);
return hash;
}
然后客户端将比较两个哈希码。如果两个哈希码不同,则客户端与服务器不同步,并将请求整个树。
问题:
由于精度是绝对重要的,我需要确保javascript始终处理整数,而永远不会将任何内容转换为浮点数。假设如果我继续像这样继续使用xor,它会永远不会变成浮点数吗?
或者也许只有一种更好的方法来做这个而不是使用xor进行散列来比较树木?
答案 0 :(得分:2)
在Javascript中,原始数字不是32位整数,变量在任何两种类型之间都不会改变;他们总是Number
s:
Number类型具有18437736874454810627(即264-253 + 3)值,表示IEEE标准二进制浮点运算中指定的双精度64位格式IEEE 754值,但9007199254740990除外(即253-2)IEEE标准的不同“非数字”值在ECMAScript中表示为单个特殊NaN值。
这意味着不同整数的支持范围基本上是-2 53 到2 53 。
这与Java's double符合的规范相同,因此可以最准确地与之比较。
我不知道你的getMostSignificantBitsAsInt
和getLeastSignificantBitsAsInt
做了什么,但如果他们解释数字就好了,就好像它是32位整数一样 - 你应该没问题 - - 即使不是。
这可能比它的价值还要多,如果尚未完成和测试,但你可以使用Javascript的bitwise operators来完成它,它将操作数视为32位整数,这正是你在找。 (具体来说,他们的规范要求在应用运算符之前在每个操作数上调用ToInt32。)
我会编写一些方法来使用这些操作数完成此操作,为这些方法编写一些测试用例,并且您的方法应该可行。当然,正如你所说,精度非常重要所以我会单独测试所有部分。
作为最后一点,您还没有说明您的目标是什么,但是您是否可以通过寻找“更小”的身份感来实现您的目标?我不想在有不稳定基础的算法上施加任何压力(关于性能或准确性)。