2012-02-03 109 views
0

我的查詢非常簡單。我更喜歡用Java編寫數值方法,但通常需要在C++中做一些事情。我喜歡Java中的高斯隨機變量,因爲它使用Marsaglia算法並保留了兩個Normal隨機變量。它在第一次通話中返回一個,在第二次通話中返回第二個,並且在第三次通話之前不再進行昂貴的計算。使用下面的oracle鏈接(在程序註釋中)我嘗試在C++中實現這個代碼,但不知道如何編寫「Synchronized」公共方法的C++版本,這將允許我使用兩個Normal隨機變量。我不是一個專業的程序員,所以任何指導將不勝感激。Marsaglia在C++中的隨機變量

總之我想保留:

V2 *乘數

// This function is Similar to the GNU 
// Java Implementation as seen on 
// http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html#nextGaussian%28%29 
double nextGaussian() { 

    double v1, v2, s, nextNextGaussian; 
    do { 
     v1 = 2 * nextUniform() - 1; // between -1.0 and 1.0 
     v2 = 2 * nextUniform() - 1; // between -1.0 and 1.0 
     s = v1 * v1 + v2 * v2; 
    } while (s >= 1 || s == 0); 
    double multiplier = sqrt(-2 * log(s)/s); 
    nextNextGaussian = v2 * multiplier; 
    return v1 * multiplier; 

} 
+0

這不是完全清楚的代碼的問題,你有* *是什麼。 – 2012-02-03 04:39:56

+0

那麼我只返回一個變量a的代碼會拋出另一個。當我需要下一個隨機變量時,我必須經歷再次生成兩個均勻隨機變量的繁重工作。這次像最後一次,我得到一個正常房車,並把另一個扔掉。在Java中,你返回一個Normal變量並保留下一次調用的第二個變量。所以你做了一半的工作。這對我的使用非常重要,因爲我的一些算法需要數天才能運行。 – JJJ 2012-02-03 04:41:26

回答

3

只是聲明nextGaussianVal靜態,即

static double nextGaussianVal; 

然後nextGaussianVal的價值將可用的nex該方法被調用。您可能還需要另一個靜態變量與當前計數跟上,像這樣:

double nextGaussian() 
{ 
    static int count = 0; 
    static double nextGaussianVal; 
    double firstGaussianVal, v1, v2, s; 

    if (count == 0) { 
     do { 
      v1 = 2 * nextUniform() - 1; // between -1.0 and 1.0 
      v2 = 2 * nextUniform() - 1; // between -1.0 and 1.0 
      s = v1 * v1 + v2 * v2; 
     } while (s >= 1 || s == 0); 
     double multiplier = sqrt(-2 * log(s)/s); 
     nextGaussianVal = v2 * multiplier; 
     firstGaussianVal = v1 * multiplier; 
     count = 1; 
     return firstGaussianVal; 
    } 

    count = 0; 
    return nextGaussianVal; 
} 

編輯:更詳細的解釋 - 在第一次調用函數時,計數被初始化爲零。基於該如果聲明,相關計算進行掃描,並且假定firstGaussianValnextGaussianVal被賦值,計數分配一個值,並firstGaussianVal返回。下一次函數被調用時,計數將具有其先前分配的值1,並且nextGaussianVal將包含它在第一次調用期間先前分配的值 - 也就是說,因爲計數現在是一個,該功能將基於if聲明,將0分配給計數並返回nextGaussianVal。沖洗,重複...

+0

我不認爲這解決了問題,但我可能是錯的。我沒有看到函數如何知道何時返回未使用的變量以及何時實際運行DO命令。你可以再詳細一點嗎? – JJJ 2012-02-03 04:56:04

+0

第二次調用在返回IF ELSE樹之前將不會被設置回0,這使得ELSE部分無法訪問? – JJJ 2012-02-03 05:08:09

+0

不,靜態變量聲明中的零值只在第一次調用該方法時被賦值,因爲它實際上是靜態的... – hatboyzero 2012-02-03 05:09:15

-1

上述建議的問題是,COUNT變量應該是BOOLEAN而不是整數。另外存儲的高斯需要也是靜態的。

我想感謝大家的幫助,幫助我達到我期望的正確解決方案。我知道這段代碼屬於一個對象。我現在有理由將它保存在一個文件中。

double nextGaussian() { 

    // Static variables allow the function to make use of 
    // both Gaussian Random variables. Generated by the polar Marsaglia 
    // method This makes the function much more efficient with will 
    // pay off for simulations 

    static bool hasNextGaussian = false; 
    static double nextNextGaussian; 
    double v1, v2, s; 

    if (!hasNextGaussian) { 

     do { 

      v1 = 2 * nextUniform() - 1; // between -1.0 and 1.0 
      v2 = 2 * nextUniform() - 1; // between -1.0 and 1.0 
      s = v1 * v1 + v2 * v2; 

     } while (s >= 1 || s == 0); 

     double multiplier = sqrt(-2 * log(s)/s); 
     nextNextGaussian = v2 * multiplier; 
     hasNextGaussian = true; 
     return v1 * multiplier; 

    } else { 

     hasNextGaussian = false; 
     return nextNextGaussian; 

    } 

} 

雙nextUniform(){

double Uniform = rand()/double(RAND_MAX); 
return Uniform; 

}

+0

除了使用布爾值而不是計數變量的事實之外,這與以上建議的功能有何不同?我仍然很難理解上面提供的例子*在這個例子中沒有工作(假設nextUniform()的定義在兩種情況下都是相同的)。 – hatboyzero 2012-02-08 16:38:51

+1

只是好奇,但回答暗指解決代碼中的一個更大的問題......這似乎沒有完全解釋/引用你的問題。這使事情有點混亂。你會介意擴大你的問題來澄清一下這裏可能缺少的部分嗎?我只想充分看到整個思路。謝謝。 – skyburner 2012-02-08 16:54:52

+0

我認爲就我而言,關鍵在於無論您是使用整數還是布爾值來管理您所處的狀態均無關緊要,這兩個示例中描述的行爲應該是**相同的**。 True與1相同,False與0相同,條件**(!hasNextGaussian)**將返回與**(count == 0)**相同的值。 – hatboyzero 2012-02-08 17:30:48