2012-02-20 70 views
0

正在研究一個項目,使用MinGW在Windows上:C++ - G ++鑄造INT翻番給出負值

C:\Users\...>g++ -dumpversion 
4.5.0 

當我編譯4.2.4我得到一個分段錯誤下G ++訴碼 - 夫婦後小時,我固定下來到該行:

double decimal = ((double) rand())/(RAND_MAX + 1); 

出於某種原因,這是給負值(並導致了另一個一件事)。 什麼原因?

編輯:CPP:

#include <iostream> 
#include "Random.h" 
#include <math.h> 

using namespace std; 
double Random::exponential(int T) { 
    double decimal = ((double) rand())/(RAND_MAX + 1); 
    // std::cout << "decimal : " << decimal << std::endl; 
    return log(1 - decimal)*(-T); 
} 
//etc 

H:

#ifndef RANDOM_H 
#define RANDOM_H 

#include <cstdlib> 
#include <math.h> 
class Random { 
public: 
    static double exponential(int T); 
    static int random_int(int min, int max); 
    static bool coin(); //50% true 50% false 
}; 

#endif /* RANDOM_H */ 

只注意到雙重包括(math.h中的),但是這不應該是一個問題

+0

這應該不會正常發生。如何聲明rand()可能存在一些問題。 – 2012-02-20 03:53:30

+0

不要在C++中使用不安全的C風格轉換(永遠)。嘗試使用static_cast或其他東西,看看它是怎麼回事。 – 2012-02-20 03:59:28

+0

@John - 你能否詳細說明一下? – 2012-02-20 04:00:09

回答

4

你的情況,RAND_MAX是存儲在其中的整數類型的最大值,因此RAND_MAX + 1會爲您提供最大負值。從技術上講,這是有符號整數溢出,這是未定義的行爲,所以可能發生任何事情

你需要做的,如J-16中指出,

double decimal = (double)rand()/((double)RAND_MAX + 1); 
+1

或'(double)RAND_MAX + 1',如果你想有'[0,1)'。 – 2012-02-20 04:06:28

+0

很好 - 只是一個細節 - 我明確地說 - 使用() - 將rand()部分轉換爲double。在10^5運行中,它在4.5.5中沒有發生過一次故障,並且在4.2.4中立即發生故障。怎麼來的 ? – 2012-02-20 04:06:54

+0

@Mr_and_Mrs_D,因爲你將它除以負值(因爲'RAND_MAX'被定義爲整數類型可以容納的最大值,當你給它加1時,它成爲最大負值),這會導致負值值 – 2012-02-20 04:08:06

1

在你的環境中,RAND_MAX可能是設置爲最高的正數,如0x7fff(32767)。當你添加一個的時候,它實際上是回到最低的負數,比如0x8000(-32768)。當然,這一切都假定是二進制補碼,並且數字將被包裝,這兩者都不是標準要求的)。

因此,因爲您將rand中的正或零值除以負值,所以大多數情況下您最終都會得到負數,偶爾會得到零。您可以在分區中使用RAND_MAX而不是RAND_MAX+1。這將避免給你一個負數,但你會遇到另一個問題。

因爲有一種可能性,即rand將返回RAND_MAX,師可以給你1的結果。當你再嘗試計算log (1 - decimal) * (-T),這是採取的零對數,你會用一個錯誤結束:log(0)是數學中沒有定義。

我建議只需通過使用像這樣避免了問題:

double Random::exponential (int T) { 
    int randVal = rand(); 
    while (randVal == RAND_MAX) 
     randVal = rand(); 

    double decimal = (double) randVal/RAND_MAX; 
    return log (1 - decimal) * (-T); 
} 

這將避免邊緣情況在以rand偶爾兩個人通話的費用。