C ++ - g ++ cast int to double给出负值

时间:2012-02-20 03:50:23

标签: c++ casting int double

正在使用Windows上的mingw项目:

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

当我在g ++ v 4.2.4下编译代码时,我遇到了一个分段错误 - 几个小时后我把它固定到了这一行:

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 */

刚刚注意到double(math.h),但这应该不是问题

2 个答案:

答案 0 :(得分:4)

在您的情况下,RAND_MAX是其存储的整数类型的最大值,因此RAND_MAX + 1为您提供最大负值。从技术上讲,这是带符号的整数溢出,这是未定义的行为,因此任何事情都可能发生。

你需要这样做,正如J-16所指出的那样,

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

答案 1 :(得分: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进行双重调用。