2015-07-01 58 views
5

您好我需要函數來根據數字(實數雙精度)和整數計算唯一的整數。JavaScript從實數和整數計算散列碼

嘗試解釋我正在開發GIS應用程序在JavaScript中,我正在處理複雜的矢量對象像多邊形(兩個座標在圓環中的點對象的數組)和線陣列的點。我需要快速的算法來識別元素已被改變,它必須非常快,因爲我的矢量對象是千點的集合。在C#中,我正在使用按位運算異或來計算來自座標的散列碼。

但javascript轉換按位操作的所有操作數爲整數,但我需要將雙精度轉換爲整數,然後按c#方式(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 

實例結果是不正確的散列== HASH1

示例2:使用字符串有正確的結果,但是從字符串計算哈希是複雜和我的事速度不夠快。

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 

例題結果是正確的哈希值!= HASH1

有一些不是轉換號碼字符串不是從每個字符計算散列更快的方法?因爲我的目標是非常大的,而且需要大量的時間和操作這種方式...

我嘗試使用TypedArrays但其實我不是成功的話做。

非常感謝您的幫助

回答

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

250倍比DataView方法快see benchmark

1

我查閱了一些哈希庫,看看他們是如何做:xxhashjsjshashes

大多數人似乎接受字符串或ArrayBuffer,也取決於在類UINT32功能上。這相當於你需要一個double的二進制表示(來自你的C#示例)。值得注意的是,我沒有找到任何解決方案,包括更奇怪的類型,除了在另一個(未回答)question

他的解決方案使用建議的方法here,它將其轉換爲各種類型的數組。這很可能是你想要的,並且是最快速準確的解決方案(我認爲)。

我強烈建議您構造代碼,以遍歷對象/數組根據需要,也是標杆的解決方案,看看它是你的現有方法相媲美如何(非工作之一,並串之一)。

+0

您好,非常感謝我在您發佈前幾分鐘自己解決了這個問題......但是非常感謝...... –

+0

我無法對您的答案發表評論,對不起。您的解決方案使用的呼叫數量超過了我所鏈接的數量,因此我預計這個數字會更快。請檢查並接受最快的答案。 – Neofish

+1

我看到這個他們不使用dataview ...我會嘗試它!謝謝 –

2

您好我試圖使用TypedArrays從數計算哈希代碼,結果是有趣的。在IE瀏覽器的性能4倍於Chrome的兩倍更好的在FireFox這種做法等於字符串版本...

var GetHashCodeNumber = function (n: number): number { 
     //create 8 byte array buffer number in js is 64bit 
     var arr = new ArrayBuffer(8); 

     //create view to array buffer 
     var dv = new DataView(arr); 

     //set number to buffer as 64 bit float 
     dv.setFloat64(0, n); 

     //now get first 32 bit from array and convert it to integer 
     // from offset 0 
     var c = dv.getInt32(0); 

     //now get next 32 bit from array and convert it to integer 
     //from offset 4 
     var d = dv.getInt32(4); 

     //XOR first end second integer numbers 
     return c^d; 
    } 

我認爲這可爲他人

編輯有用:使用一個緩衝和數據視圖更快!