1

I have a tree in the client, in javascript:

function Node(uuid, someData, versionNum) {
   this.uuid = uuid;
   this.someData = someData;
   this.versionNum = versionNum;
   this.childNodes = [];
}

and the same tree in the server, in java:

public class Node {
   UUID uuid;
   String someData;
   int versionNum;
   List<Node> childNodes;
}

The client will send a request to the server every five seconds, asking for a hash of the tree. The idea is that the tree's hash will be recursively calculated like this:

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;
}

On the client, once it receives the response from the server, with the server's calculated hash, the client will then calculate its own hash of its local tree:

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;
}

and then the client will compare the two hash codes. If the two hash codes are different, then the client is out of sync with the server, and will request the entire tree.

The question:

Since precision is of absolute importance, I need to make sure that the javascript is always dealing in integers, and never converts anything to floats. Is it save to assume that if I just keep on using xor like this, then it will never become a float?

Or perhaps there's just a better way of doing this than hashing with xor to compare the trees?

Verdagon
  • 2,456
  • 3
  • 22
  • 36
  • Your Javascript code is invalid. Perhaps you mean `var` instead of `long`? –  Oct 01 '13 at 02:25
  • Thanks, fixed. I was dumb and didnt try running it. I'll run it now just to doublecheck. – Verdagon Oct 01 '13 at 02:26
  • As a side note, you DO realise that if some nodes in the tree change their position in their tree but not their UUID; for example two nodes are swapped over - then this change won't show up at the client, right? – Dawood ibn Kareem Oct 01 '13 at 02:58
  • Yep, I used to add some extra information into the hash to accommodate that, but then i found out that luckily, a node can never move. – Verdagon Oct 01 '13 at 03:06

1 Answers1

2

In Javascript, primitive numbers are not 32-bit integers, and variables don't change between any two types; they are always Numbers:

The Number type has exactly 18437736874454810627 (that is, 264−253+3) values, representing the double-precision 64-bit format IEEE 754 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic, except that the 9007199254740990 (that is, 253−2) distinct “Not-a-Number” values of the IEEE Standard are represented in ECMAScript as a single special NaN value.

This means the supported range for distinct integers is basically –253 to 253.

This is the same spec that Java's double conforms too, so it can be most accurately compared with that.

I don't know what your getMostSignificantBitsAsInt and getLeastSignificantBitsAsInt do, but you should be fine if they interpret the Number as if it was a 32-bit integer -- even though it isn't.

This might be more work than it's worth, if it's not already done and tested, but you may be able to accomplish it using Javascript's bitwise operators, which treat their operands as 32-bit integers, which is exactly what you are looking for. (Specifically, they spec requires calls to ToInt32 on each operand before the operator is applied.)

I would write some methods to accomplish this using these operands, write some test cases for those methods, and your method should work. Of course, as you said, precision is hugely important so I would unit test all the parts.


As a final note, you haven't said what your underlying goal is, but could you accomplish your goals by looking for a "smaller" sense of identity to hash? I would hate to put any sort of pressure (with regards to performance or accuracy) on an algorithm with shaky underpinnings.

Community
  • 1
  • 1
Nicole
  • 32,841
  • 11
  • 75
  • 101
  • Thanks! But how can I safely interpret the number as if it was a 32bit int, if underneath it's a double? Don't I have to worry about things like epsilons, etc? And is xor on doubles even defined? – Verdagon Oct 01 '13 at 02:31
  • @Verdagon Updated -- sounds like the bitwise operators treat numbers as if they were 32 bit operators, so they may be your friend. – Nicole Oct 01 '13 at 02:38
  • Awesome, that ToInt32 thing is exactly what I was hoping they did. Thanks! – Verdagon Oct 01 '13 at 02:43
  • @Verdagon Hey I learned something too. :) http://es5.github.io/ is your friend when it comes to the inner workings of JS. – Nicole Oct 01 '13 at 02:44