JavaScript从实数和整数

时间:2015-07-01 09:06:44

标签: javascript html5 typescript

您好我需要函数来计算从数字(实数双精度)和整数的唯一整数。

尝试解释我正在使用javascript开发GIS应用程序,我正在处理复杂的矢量对象,如polygon(点对象数组,环中有两个坐标)和点数组。我需要快速算法来识别元素已被更改它必须非常快,因为我的矢量对象是千点的集合。在C#中,我使用按位运算XOR从坐标计算哈希码。

但是javascript将按位运算中的所有操作数转换为整数但我需要在c#way(binnary)中按位置应用之前将双精度转换为整数。在反射器中,我看到c#计算哈希码这样的双倍,我需要这个函数在javascript中尽可能快。

public override unsafe int GetHashCode() //from System.Double
{
    double num = this;
    if (num == 0.0)
    {
        return 0;
    }
    long num2 = *((long*) &num);
    return (((int) num2) ^ ((int) (num2 >> 32)));
}

示例:

var rotation = function (n) {
    n = (n >> 1) | ((n & 0x001) << 31);
    return n;
}

var x: number = 1;
var y: number = 5;

var hash = x ^ rotation(y); // result is -2147483645

var x1: number = 1.1;
var y1: number = 5;

var hash1 = x1 ^ rotation(y1); // result is -2147483645

示例结果不正确hash == hash1

示例2:使用to string得到正确的结果但是从字符串计算Hash是复杂的,而且事情还不够快。

    var rotation = function (n) {
        n = (n >> 1) | ((n & 0x001) << 31);
        return n;
    }

     var GetHashCodeString = function(str: string): number {
        var hash = 0, i, l, ch;
        if (str.length == 0) return hash;
        for (i = 0, l = str.length; i < l; i++) {
            ch = str.charCodeAt(i);
            hash = ((hash << 5) - hash) + ch;
            hash |= 0; // Convert to 32bit integer
        }
        return hash;
     }

    var x: number = 1;
    var y: number = 5;

    var hash = GetHashCodeString(x.toString()) ^ rotation(GetHashCodeString(y.toString()));
    //result is -2147483605
    var x1: number = 1.1;
    var y1: number = 5;

    var hash1 = GetHashCodeString(x1.toString()) ^ rotation(GetHashCodeString(y1.toString()));
   //result is -2147435090

示例2结果是正确的哈希!= hash1

是否有比将数字转换为字符串更快的方法而不是从每个字符计算哈希?因为我的对象非常大,这将需要大量的时间和操作......

我尝试使用TypedArrays但是我没有成功。

非常感谢你的帮助

3 个答案:

答案 0 :(得分:2)

您好我尝试使用TypedArrays从数字计算哈希代码,结果很有趣。在IE中,FireFox中Chrome 2x的性能提升了4倍,这种方法等同于字符串版本...

{{1}}

我认为这对某人有用

编辑:使用一个缓冲区,DataView更快!

答案 1 :(得分:1)

我查找了一些哈希库,看看他们是如何做到的:xxhashjsjshashes等。

大多数似乎采用字符串或ArrayBuffer,并且还依赖于类似UINT32的功能。这相当于您需要double的二进制表示(来自您的C#示例)。值得注意的是,除了另一个(未答复的)question之外,我没有找到任何包含更多奇怪类型的解决方案。

他的解决方案使用了一个方法here,将其转换为各种类型的数组。这很可能是你想要的,也是最准确的解决方案(我认为)。

我强烈建议您根据需要构建代码以遍历对象/数组,并对解决方案进行基准测试,以查看它与现有方法(非工作方法和字符串1)的可比性。

答案 2 :(得分:1)

这是在JavaScript中执行此操作的更快方法。

const kBuf = new ArrayBuffer(8);
const kBufAsF64 = new Float64Array(kBuf);
const kBufAsI32 = new Int32Array(kBuf);

function hashNumber(n) {
  // Remove this `if` if you want 0 and -0 to hash to different values.
  if (~~n === n) {
    return ~~n;
  }
  kBufAsF64[0] = n;
  return kBufAsI32[0] ^ kBufAsI32[1];
}

DataView方法 快250倍see benchmark